﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область СлужебныйПрограммныйИнтерфейс

// Возвращаемое значение:
//  ФиксированнаяСтруктура:
//    * БезРазделовИОбъектов - Булево
//    * ВсеРазделыБезОбъектов - Булево
//    * ДатыЗапретаЗагрузкиВнедрены - Булево
//    * ЕдинственныйРаздел - ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения
//    * ИспользоватьВнешнихПользователей - Булево
//    * ПоказыватьРазделы - Булево
//    * ПустыеСсылкиУзловПлановОбмена - ФиксированныйМассив
//    * Разделы - ФиксированноеСоответствие из КлючИЗначение:
//        ** Ключ - Строка
//        ** Значение - ФиксированнаяСтруктура:
//             *** Имя - Строка
//             *** Представление - Строка
//             *** Ссылка - ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения
//             *** ТипыОбъектов - ФиксированныйМассив
//    * РазделыБезОбъектов - ФиксированныйМассив
//
Функция СвойстваРазделов() Экспорт
	
	Возврат ПараметрыСеанса.ДействующиеДатыЗапретаИзменения.СвойстваРазделов;
	
КонецФункции

// Устанавливает необходимость обновления версии дат запрета изменения после изменения данных
// в режиме загрузки или непосредственно обновляет версию (загрузка в рамках обновления ИБ).
//
// Вызывается из события ПриЗаписи регистров ДатыЗапретаИзменения и СоставыГруппПользователей.
//
// Параметры:
//  Объект - РегистрСведенийНаборЗаписей.ДатыЗапретаИзменения
//         - РегистрСведенийНаборЗаписей.СоставыГруппПользователей
// 
Процедура ОбновитьВерсиюДатЗапретаИзмененияПриЗагрузкеДанных(Объект) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	Если ЗначениеЗаполнено(Объект.ОбменДанными.Отправитель) Тогда
		ПараметрыСеанса.ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных = Истина;
	Иначе
		ОбновитьВерсиюДатЗапретаИзменения();
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Обработчики событий подсистем конфигурации.

// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииОбработчиковУстановкиПараметровСеанса.
Процедура ПриДобавленииОбработчиковУстановкиПараметровСеанса(Обработчики) Экспорт
	
	Обработчики.Вставить("ПропуститьПроверкуЗапретаИзменения",
		"ДатыЗапретаИзмененияСлужебный.УстановкаПараметровСеанса");
	
	Обработчики.Вставить("ДействующиеДатыЗапретаИзменения",
		"ДатыЗапретаИзмененияСлужебный.УстановкаПараметровСеанса");
	
	Обработчики.Вставить("ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных",
		"ДатыЗапретаИзмененияСлужебный.УстановкаПараметровСеанса");
	
	Обработчики.Вставить("ПраваДоступаКДатамЗапрета",
		"ДатыЗапретаИзмененияСлужебный.УстановкаПараметровСеанса");
	
КонецПроцедуры

// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
	
	Обработчик = Обработчики.Добавить();
	Обработчик.ОбщиеДанные = Истина;
	Обработчик.Версия = "*";
	Обработчик.Процедура = "ДатыЗапретаИзмененияСлужебный.ОбновитьРазделыДатЗапретаИзменения";
	Обработчик.РежимВыполнения = "Оперативно";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.НачальноеЗаполнение = Истина;
	Обработчик.Процедура = "ДатыЗапретаИзмененияСлужебный.УстановитьНачальнуюДатуЗапретаИзменения";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.ОбщиеДанные = Истина;
	Обработчик.Версия = "2.4.1.1";
	Обработчик.Процедура = "ДатыЗапретаИзмененияСлужебный.ОчиститьПредопределенныеЭлементыРазделовДатЗапрета";
	Обработчик.РежимВыполнения = "Оперативно";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "2.4.1.1";
	Обработчик.Процедура = "ДатыЗапретаИзмененияСлужебный.ЗаменитьРазделыДатЗапретаНаНовые";
	
	Обработчик = Обработчики.Добавить();
	Обработчик.Версия = "3.1.8.75";
	Обработчик.Процедура = "ДатыЗапретаИзмененияСлужебный.ДополнитьНастройкиУказанныхАдресатов";
	
КонецПроцедуры

// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхГлавному.
Процедура ПриОтправкеДанныхГлавному(ЭлементДанных, ОтправкаЭлемента, Получатель) Экспорт
	
	Если НаборЗаписейТолькоСДатамиЗапретаЗагрузки(ЭлементДанных) Тогда
		ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
	КонецЕсли;
	
КонецПроцедуры

// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхПодчиненному.
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель) Экспорт
	
	Если НаборЗаписейТолькоСДатамиЗапретаЗагрузки(ЭлементДанных) Тогда
		ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
	КонецЕсли;
	
КонецПроцедуры

// См. СтандартныеПодсистемыСервер.ПриПолученииДанныхОтГлавного.
Процедура ПриПолученииДанныхОтГлавного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Отправитель) Экспорт
	
	// Стандартная обработка не переопределяется.
	Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать Тогда
		Возврат;
	КонецЕсли;
	
	Если НаборЗаписейТолькоСДатамиЗапретаЗагрузки(ЭлементДанных) Тогда
		ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
	КонецЕсли;
	
КонецПроцедуры

// См. СтандартныеПодсистемыСервер.ПриПолученииДанныхОтПодчиненного.
Процедура ПриПолученииДанныхОтПодчиненного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Отправитель) Экспорт
	
	// Стандартная обработка не переопределяется.
	Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать Тогда
		Возврат;
	КонецЕсли;
	
	Если НаборЗаписейТолькоСДатамиЗапретаЗагрузки(ЭлементДанных) Тогда
		ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
	КонецЕсли;
	
КонецПроцедуры

// Обработчики событий подсистемы ВариантыОтчетов.

// См. ВариантыОтчетовПереопределяемый.НастроитьВариантыОтчетов.
Процедура ПриНастройкеВариантовОтчетов(Настройки) Экспорт
	
	МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ДатыЗапретаЗагрузки);
	МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ДатыЗапретаИзменения);
	
КонецПроцедуры

// Обработчики событий подсистемы Пользователи.

// См. ИнтеграцияПодсистемБСП.ПослеОбновленияСоставовГруппПользователей.
Процедура ПослеОбновленияСоставовГруппПользователей(УчастникиИзменений, ИзмененныеГруппы) Экспорт
	
	ОбновитьВерсиюДатЗапретаИзменения();
	
КонецПроцедуры

// Обработчики событий подсистемы Управление доступом.

// См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт
	
	Списки.Вставить(Метаданные.РегистрыСведений.ДатыЗапретаИзменения, Истина);
	
КонецПроцедуры

// Обработчики событий библиотеки ТехнологияСервиса.

// См. ВыгрузкаЗагрузкаДанныхПереопределяемый.ПриЗаполненииТиповОбщихДанныхПоддерживающихСопоставлениеСсылокПриЗагрузке
Процедура ПриЗаполненииТиповОбщихДанныхПоддерживающихСопоставлениеСсылокПриЗагрузке(Типы) Экспорт
	
	// В разделенных данных используются только ссылки с поставляемыми уникальными идентификаторами,
	// указанными в процедуре ПриЗаполненииРазделовДатЗапретаИзменения
	// общего модуля ДатыЗапретаИзмененияПереопределяемый.
	Типы.Добавить(Метаданные.ПланыВидовХарактеристик.РазделыДатЗапретаИзменения);
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// Основные процедуры и функции.

// Параметры:
//  ИмяПараметра - Строка
//  УстановленныеПараметры - Массив из Строка
//
Процедура УстановкаПараметровСеанса(ИмяПараметра, УстановленныеПараметры) Экспорт
	
	Если ИмяПараметра = "ДействующиеДатыЗапретаИзменения" Тогда
		Значение = ЗначениеПараметраСеансаДействующиеДатыЗапретаИзменения();
		ПараметрыСеанса.ДействующиеДатыЗапретаИзменения = Значение;
		УстановленныеПараметры.Добавить("ДействующиеДатыЗапретаИзменения");
		ПоследняяПроверка = ДатыЗапретаИзмененияСлужебныйПовтИсп.ПоследняяПроверкаВерсииДействующихДатЗапрета();
		ПоследняяПроверка.Дата = ТекущаяДатаСеанса();
		
	ИначеЕсли ИмяПараметра = "ПропуститьПроверкуЗапретаИзменения" Тогда
		ПараметрыСеанса.ПропуститьПроверкуЗапретаИзменения = Ложь;
		УстановленныеПараметры.Добавить("ПропуститьПроверкуЗапретаИзменения");
		
	ИначеЕсли ИмяПараметра = "ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных" Тогда
		ПараметрыСеанса.ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных = Ложь;
		УстановленныеПараметры.Добавить("ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных");
		
	ИначеЕсли ИмяПараметра = "ПраваДоступаКДатамЗапрета" Тогда
		Права = Новый Массив;
		// АПК:515-выкл - №737.4 проверка по ролям, так как право есть всегда.
		Если Пользователи.РолиДоступны("ЧтениеДатЗапретаИзменения, ДобавлениеИзменениеДатЗапретаИзменения",, Ложь) Тогда
			Права.Добавить("ЧтениеДатЗапретаИзменения");
		КонецЕсли;
		Если Пользователи.РолиДоступны("ДобавлениеИзменениеДатЗапретаИзменения",, Ложь) Тогда
			Права.Добавить("ИзменениеДатЗапретаИзменения");
		КонецЕсли;
		Если Пользователи.РолиДоступны("ЧтениеДатЗапретаЗагрузки, ДобавлениеИзменениеДатЗапретаЗагрузки",, Ложь) Тогда
			Права.Добавить("ЧтениеДатЗапретаЗагрузки");
		КонецЕсли;
		Если Пользователи.РолиДоступны("ДобавлениеИзменениеДатЗапретаЗагрузки",, Ложь) Тогда
			Права.Добавить("ИзменениеДатЗапретаЗагрузки");
		КонецЕсли;
		// АПК:515-вкл
		Если ЗначениеЗаполнено(Права) Тогда
			ПраваДоступаКДатамЗапрета = "," + СтрСоединить(Права, "," + Символы.ПС + ",") + ",";
		Иначе
			ПраваДоступаКДатамЗапрета = "";
		КонецЕсли;
		ПараметрыСеанса.ПраваДоступаКДатамЗапрета = ПраваДоступаКДатамЗапрета;
		УстановленныеПараметры.Добавить("ПраваДоступаКДатамЗапрета");
	КонецЕсли;
	
КонецПроцедуры

// Обработчик подписки ОбновлениеВерсииДатЗапретаИзмененияПослеЗагрузкиДанных
// на событие ПриЗаписи любого плана обмена.
//
Процедура ОбновлениеВерсииДатЗапретаИзмененияПослеЗагрузкиДанныхПриЗаписи(Источник, Отказ) Экспорт
	
	// В режиме ОбменДанными.Загрузка необходимо обновлять УИД в константе ВерсияДатЗапретаИзменения,
	// который позволять сеансам определить, что нужно обновить кэш дат запрета изменения в памяти.
	
	УстановитьПривилегированныйРежим(Истина);
	
	Если ПараметрыСеанса.ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных Тогда
		ОбновитьВерсиюДатЗапретаИзменения();
		ПараметрыСеанса.ОбновитьВерсиюДатЗапретаИзмененияПослеЗагрузкиДанных = Ложь;
	КонецЕсли;
	
	Если Источник.ОбменДанными.Загрузка Тогда
		Возврат;
	КонецЕсли;
	
КонецПроцедуры

// Обновляет версию дат запрета после изменения.
Процедура ОбновитьВерсиюДатЗапретаИзменения() Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	Константы.ВерсияДатЗапретаИзменения.Установить(Новый УникальныйИдентификатор);
	
	ПоследняяПроверка = ДатыЗапретаИзмененияСлужебныйПовтИсп.ПоследняяПроверкаВерсииДействующихДатЗапрета();
	ПоследняяПроверка.Дата = '00010101';
	
КонецПроцедуры

// Возвращает дату запрета, рассчитанную по описанию относительной даты запрета.
//
// Параметры:
//  ОписаниеДатыЗапрета - Строка - содержит описание относительной даты запрета.
//  ДатаЗапрета         - Дата - абсолютная дата, полученная из регистра.
//  НачалоДня           - Дата - текущая дата сеанса на начало дня.
//                      - Неопределено - вычислить автоматически.
//
// Возвращаемое значение:
//  Дата
//
Функция ДатаЗапретаПоОписанию(ОписаниеДатыЗапрета, ДатаЗапрета, НачалоДня = '00010101') Экспорт
	
	Если Не ЗначениеЗаполнено(ОписаниеДатыЗапрета) Тогда
		Возврат ДатаЗапрета;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(НачалоДня) Тогда
		НачалоДня = НачалоДня(ТекущаяДатаСеанса());
	КонецЕсли;
	
	Сутки = 60*60*24;
	КоличествоДнейРазрешения = 0;
	
	ВариантДатыЗапрета    = СтрПолучитьСтроку(ОписаниеДатыЗапрета, 1);
	КоличествоДнейСтрокой = СтрПолучитьСтроку(ОписаниеДатыЗапрета, 2);
	
	Если ЗначениеЗаполнено(КоличествоДнейСтрокой) Тогда
		ОписаниеТипа = Новый ОписаниеТипов("Число");
		КоличествоДнейРазрешения = ОписаниеТипа.ПривестиЗначение(КоличествоДнейСтрокой);
	КонецЕсли;
	
	Если ВариантДатыЗапрета = "КонецПрошлогоГода" Тогда
		ТекущаяДатаЗапрета    = НачалоГода(НачалоДня)          - Сутки;
		ПредыдущаяДатаЗапрета = НачалоГода(ТекущаяДатаЗапрета) - Сутки;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлогоКвартала" Тогда
		ТекущаяДатаЗапрета    = НачалоКвартала(НачалоДня)          - Сутки;
		ПредыдущаяДатаЗапрета = НачалоКвартала(ТекущаяДатаЗапрета) - Сутки;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлогоМесяца" Тогда
		ТекущаяДатаЗапрета    = НачалоМесяца(НачалоДня)          - Сутки;
		ПредыдущаяДатаЗапрета = НачалоМесяца(ТекущаяДатаЗапрета) - Сутки;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлойНедели" Тогда
		ТекущаяДатаЗапрета    = НачалоНедели(НачалоДня)          - Сутки;
		ПредыдущаяДатаЗапрета = НачалоНедели(ТекущаяДатаЗапрета) - Сутки;
		
	ИначеЕсли ВариантДатыЗапрета = "ПредыдущийДень" Тогда
		ТекущаяДатаЗапрета    = НачалоДня(НачалоДня)          - Сутки;
		ПредыдущаяДатаЗапрета = НачалоДня(ТекущаяДатаЗапрета) - Сутки;
	Иначе
		Возврат '39990303'; // Неизвестный формат.
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ТекущаяДатаЗапрета) Тогда
		СрокРазрешения = ТекущаяДатаЗапрета + КоличествоДнейРазрешения * Сутки;
		Если Не НачалоДня > СрокРазрешения Тогда
			ТекущаяДатаЗапрета = ПредыдущаяДатаЗапрета;
		КонецЕсли;
	КонецЕсли;
	
	Возврат ТекущаяДатаЗапрета;
	
КонецФункции

// Возвращаемое значение:
//   Структура:
//    * ПроверкаЗапретаИзменения    - Булево - если установить Ложь, проверка запрета изменения для пользователей 
//                                    будет пропущена. По умолчанию Истина.
//    * УзелПроверкиЗапретаЗагрузки - Неопределено - (начальное значение) выполнить проверку изменения данных.
//                                  - ПланОбменаСсылка - выполнить проверку загрузки данных для указанного узла.
//    * ОписаниеОшибки              - Null      - если возвращать описание найденных запретов не требуются (по умолчанию).
//                                  - Строка    - если нужно вернуть текстовое описание.
//                                  - Структура - если нужно вернуть структурное описание найденных запретов,
//                                                подробнее см. функцию ДатыЗапретаИзменения.НайденЗапретИзмененияДанных.
//
Функция ПараметрыПроверкиДатЗапрета() Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("ПроверкаЗапретаИзменения",    Ложь);
	Результат.Вставить("УзелПроверкиЗапретаЗагрузки", Неопределено);
	Результат.Вставить("ОписаниеОшибки",              Null);
	Возврат Результат;

КонецФункции

// Проверяет даты запрета изменения/загрузки данных для объекта.
// В случае если изменение/загрузка невозможно, устанавливает параметр Отказ в Истина.
//
// Параметры:
//  Источник        - СправочникОбъект
//                  - ПланВидовХарактеристикОбъект
//                  - ПланСчетовОбъект
//                  - ПланВидовРасчетаОбъект
//                  - БизнесПроцессОбъект
//                  - ЗадачаОбъект
//                  - ПланОбменаОбъект
//                  - ДокументОбъект - объект данных.
//                  - РегистрСведенийНаборЗаписей
//                  - РегистрНакопленияНаборЗаписей
//                  - РегистрБухгалтерииНаборЗаписей
//                  - РегистрРасчетаНаборЗаписей - набор записей.
//                  - УдалениеОбъекта - удаление объекта при загрузке.
//
//  ИсточникРегистр - Булево - Ложь - Источник является регистром, иначе объектом.
//
//  Замещение       - Булево - если источник является регистром и выполняется добавление,
//                    нужно указать Ложь.
//
//  Удаление        - Булево - если источник является объектом и выполняется удаление объекта,
//                    нужно указать Истина.
//
//  ДополнительныеПараметры - Неопределено - параметры имеют начальные значения.
//                          - см. ПараметрыПроверкиДатЗапрета
//
// Возвращаемое значение:
//   Структура:
//    * ИзменениеЗапрещено - Булево - Истина, если объект не проходит проверки дат запрета.
//    * ОписаниеОшибки     - Null
//                         - Строка
//                         - Структура - результат зависит от ДополнительныеПараметры.ОписаниеОшибки.
//
Функция ПроверитьДатыЗапретаИзмененияЗагрузкиДанных(Источник, ИсточникРегистр, Замещение, Удаление, 
	ДополнительныеПараметры = Неопределено) Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("ИзменениеЗапрещено", Ложь);
	Результат.Вставить("ОписаниеОшибки", "");
	
	ПроверкаЗапретаИзменения    = Истина;
	УзелПроверкиЗапретаЗагрузки = Неопределено;
	
	Если ТипЗнч(ДополнительныеПараметры) = Тип("Структура") Тогда
		ДополнительныеПараметры.Свойство("ПроверкаЗапретаИзменения",    ПроверкаЗапретаИзменения);
		ДополнительныеПараметры.Свойство("УзелПроверкиЗапретаЗагрузки", УзелПроверкиЗапретаЗагрузки);
		ДополнительныеПараметры.Свойство("ОписаниеОшибки",              Результат.ОписаниеОшибки);
	КонецЕсли;
	
	ВерсияОбъекта = "";
	Если ПропуститьПроверкуДатЗапрета(Источник, ПроверкаЗапретаИзменения,
			УзелПроверкиЗапретаЗагрузки, ВерсияОбъекта) Тогда
		Возврат Результат;
	КонецЕсли;
	
	Если НЕ ИсточникРегистр И НЕ Удаление И НЕ Источник.ЭтоНовый() Тогда
	
		Если ИзменениеЗапрещено(
				?(ВерсияОбъекта <> "СтараяВерсия", Источник, Источник.Метаданные().ПолноеИмя()),
				?(ВерсияОбъекта <> "НоваяВерсия",  Источник.Ссылка, Неопределено),
				Результат.ОписаниеОшибки,
				УзелПроверкиЗапретаЗагрузки) Тогда
			
			Результат.ИзменениеЗапрещено = Истина;
		КонецЕсли;
		
	ИначеЕсли ИсточникРегистр И Замещение Тогда
		
		Если ИзменениеЗапрещено(
				?(ВерсияОбъекта <> "СтараяВерсия", Источник, Источник.Метаданные().ПолноеИмя()),
				?(ВерсияОбъекта <> "НоваяВерсия",  Источник.Отбор, Неопределено),
				Результат.ОписаниеОшибки,
				УзелПроверкиЗапретаЗагрузки) Тогда
			
			Результат.ИзменениеЗапрещено = Истина;
		КонецЕсли;
		
	ИначеЕсли ТипЗнч(Источник) = Тип("УдалениеОбъекта") Тогда
		
		Если ВерсияОбъекта <> "НоваяВерсия"
		   И ИзменениеЗапрещено(Источник.Ссылка.Метаданные().ПолноеИмя(), Источник.Ссылка,
				Результат.ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки) Тогда
			
			Результат.ИзменениеЗапрещено = Истина;
		КонецЕсли;
		
	Иначе
		// Выполняется при условии:
		//     НЕ ИсточникРегистр И Источник.ЭтоНовый()
		// ИЛИ    ИсточникРегистр И НЕ Замещение
		// ИЛИ НЕ ИсточникРегистр И Удаление.
		Если ВерсияОбъекта <> "СтараяВерсия"
		   И ИзменениеЗапрещено(Источник, Неопределено,	Результат.ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки) Тогда
			
			Результат.ИзменениеЗапрещено = Истина;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Проверяет необходимость проверки запрета изменения или загрузки данных.
//
// Возвращаемое значение:
//  Булево - Истина, если проверка не требуется.
//
Функция ПропуститьПроверкуДатЗапрета(Объект, ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки, 
	ВерсияОбъекта) Экспорт
	
	Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта")
	   И Объект.ДополнительныеСвойства.Свойство("ПропуститьПроверкуЗапретаИзменения") Тогда
		
		Возврат Истина;
	КонецЕсли;
	
	Если ПроверкаДатЗапретаОтключена(ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки) Тогда
		Возврат Истина;
	КонецЕсли;
	
	ДатыЗапретаИзмененияПереопределяемый.ПередПроверкойЗапретаИзменения(
		Объект, ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки, ВерсияОбъекта);
	
	Возврат ПроверкаЗапретаИзменения    = Ложь          // НЕ проверять запрет изменения.
	      И УзелПроверкиЗапретаЗагрузки = Неопределено; // НЕ проверять запрет загрузки.
	
КонецФункции

Функция ПроверкаДатЗапретаОтключена(ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	Если ПараметрыСеанса.ПропуститьПроверкуЗапретаИзменения Тогда
		Возврат Истина;
	КонецЕсли;
	УстановитьПривилегированныйРежим(Ложь);
	
	Если ЗапретИзмененияДанныхНеИспользуется(ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки) Тогда
		Возврат Истина;
	КонецЕсли;
	
	Если ОбновлениеИнформационнойБазы.ВыполняетсяОбновлениеИнформационнойБазы()
	 Или ОбновлениеИнформационнойБазы.ЭтоВызовИзОбработчикаОбновления() Тогда
		
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

// См. ДатыЗапретаИзменения.ИзменениеЗапрещено.
Функция ИзменениеЗапрещено(Данные, ИдентификаторДанных, ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	ЗапретНайден = Ложь;
	ДействующиеДаты = ДействующиеДатыЗапрета();
	
	// Проверка старой версии объекта или набора записей.
	Если ИдентификаторДанных <> Неопределено Тогда
		ПараметрыСообщенияОЗапрете = ДатыЗапретаИзменения.ПараметрыСообщенияОЗапрете();
		ПараметрыСообщенияОЗапрете.НоваяВерсия = Ложь;
		
		// Данные - это имя таблицы, требуемое для свойства ИдентификаторДанных типа Отбор,
		// а также когда исходные данные имеют тип УдалениеОбъекта.
		
		Если ТипЗнч(ИдентификаторДанных) = Тип("Отбор") Тогда
			ОтборСтруктура = Новый Структура;
			ОтборСтруктура.Вставить("Регистр", Данные);
			ОтборСтруктура.Вставить("Отбор", ИдентификаторДанных);
			ПараметрыСообщенияОЗапрете.Данные = ОтборСтруктура;
		Иначе
			ПараметрыСообщенияОЗапрете.Данные = ИдентификаторДанных;
		КонецЕсли;
		
		ДанныеДляПроверки = ДанныеДляПроверкиИзБазыДанных(Данные,
			ИдентификаторДанных, ДействующиеДаты, УзелПроверкиЗапретаЗагрузки);
		
		ЗапретНайден = НайденЗапретИзмененияДанных(ДанныеДляПроверки,
			ПараметрыСообщенияОЗапрете, ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки, ДействующиеДаты);
	КонецЕсли;
	
	// Проверка новой версии объекта или набора записей.
	Если Не ЗапретНайден И ТипЗнч(Данные) <> Тип("Строка") Тогда
		
		ПараметрыСообщенияОЗапрете = ДатыЗапретаИзменения.ПараметрыСообщенияОЗапрете();
		ПараметрыСообщенияОЗапрете.НоваяВерсия = Истина;
		ПараметрыСообщенияОЗапрете.Данные = Данные;
		
		ДанныеДляПроверки = ДанныеДляПроверкиИзОбъекта(Данные, ДействующиеДаты, УзелПроверкиЗапретаЗагрузки);
		
		ЗапретНайден = НайденЗапретИзмененияДанных(ДанныеДляПроверки,
			ПараметрыСообщенияОЗапрете, ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки, ДействующиеДаты);
	КонецЕсли;
	
	Возврат ЗапретНайден;
	
КонецФункции

// Найти даты запрета по проверяемым данным для указанного пользователя или узла плана обмена.
// См. ДатыЗапретаИзменения.НайденЗапретИзмененияДанных.
//
// Параметры:
//  ДанныеДляПроверки           - см. ДатыЗапретаИзменения.ШаблонДанныхДляПроверки
//  ПараметрыСообщенияОЗапрете  - см. ДатыЗапретаИзменения.ПараметрыСообщенияОЗапрете
//  ОписаниеОшибки              - см. ДатыЗапретаИзменения.НайденЗапретИзмененияДанных.ОписаниеОшибки
//  УзелПроверкиЗапретаЗагрузки - см. ДатыЗапретаИзменения.НайденЗапретИзмененияДанных.УзелПроверкиЗапретаЗагрузки
//
//  ДействующиеДаты - см. ДатыЗапретаИзмененияСлужебный.ЗначениеПараметраСеансаДействующиеДатыЗапретаИзменения
//
// Возвращаемое значение:
//  Булево - Истина, если найден хотя бы один запрет изменения.
//
Функция НайденЗапретИзмененияДанных(Знач ДанныеДляПроверки, ПараметрыСообщенияОЗапрете,
			ОписаниеОшибки, УзелПроверкиЗапретаЗагрузки, ДействующиеДаты = Неопределено) Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	Если ДействующиеДаты = Неопределено Тогда
		ДействующиеДаты = ДействующиеДатыЗапрета();
	КонецЕсли;
	
	ЗапретИспользуется = ?(УзелПроверкиЗапретаЗагрузки = Неопределено,
		ДействующиеДаты.ЗапретИзмененияИспользуется,
		ДействующиеДаты.ЗапретЗагрузкиИспользуется);
	
	Если Не ЗапретИспользуется Тогда
		Возврат Ложь;
	КонецЕсли;
	
	СвойстваРазделов = ДействующиеДаты.СвойстваРазделов;
	ПустойРаздел = ПустаяСсылка(Тип("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения"));
	
	ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка в функции %1 общего модуля %2.'"),
		"НайденЗапретИзмененияДанных",
		"ДатыЗапретаИзменения")
		+ Символы.ПС
		+ Символы.ПС;
	
	// Приведение данных в соответствие варианту встраивания.
	Для Каждого Строка Из ДанныеДляПроверки Цикл
		
		Если Строка.Раздел = Неопределено Тогда
			Строка.Раздел = ПустойРаздел;
		КонецЕсли;
		
		СвойстваРаздела = СвойстваРазделов.Разделы.Получить(Строка.Раздел); // см. ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРаздела
		Если СвойстваРаздела = Неопределено Тогда
			ТекстОшибки = ЗаголовокОшибки + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'В параметре %1 указан несуществующий раздел ""%2"".'"),
				"ДанныеДляПроверки",
				Строка.Раздел);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		
		Если СвойстваРазделов.БезРазделовИОбъектов Тогда
			Строка.Раздел = ПустойРаздел;
			Строка.Объект = ПустойРаздел;
		Иначе
			Если ЗначениеЗаполнено(СвойстваРазделов.ЕдинственныйРаздел) Тогда
				Строка.Раздел = СвойстваРазделов.ЕдинственныйРаздел;
			Иначе
				Строка.Раздел = СвойстваРаздела.Ссылка;
			КонецЕсли;
			
			Если СвойстваРазделов.ВсеРазделыБезОбъектов
			 Или Не ЗначениеЗаполнено(Строка.Объект) Тогда
				
				Строка.Объект = Строка.Раздел;
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	// Свертка лишних строк, чтобы сократить число проверок и сообщений.
	РазделыИОбъекты = ДанныеДляПроверки.Скопировать(, "Раздел, Объект");
	РазделыИОбъекты.Свернуть("Раздел, Объект");
	Отбор = Новый Структура("Раздел, Объект");
	РазделыИОбъекты.Колонки.Добавить("Дата",
		Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)));
	
	Для Каждого РазделИОбъект Из РазделыИОбъекты Цикл
		ЗаполнитьЗначенияСвойств(Отбор, РазделИОбъект);
		Строки = ДанныеДляПроверки.НайтиСтроки(Отбор);
		МинимальнаяДата = Неопределено;
		Для Каждого Строка Из Строки Цикл
			ТекущаяДата = НачалоДня(Строка.Дата);
			Если МинимальнаяДата = Неопределено Тогда
				МинимальнаяДата = ТекущаяДата;
			КонецЕсли;
			Если ТекущаяДата < МинимальнаяДата Тогда
				МинимальнаяДата = ТекущаяДата;
			КонецЕсли;
		КонецЦикла;
		РазделИОбъект.Дата = МинимальнаяДата;
	КонецЦикла;
	ДанныеДляПроверки = РазделыИОбъекты;
	
	// Приоритеты дат запрета изменения.
	// 1. Если есть настройка для пользователя, то используется она,
	//    а настройки для групп пользователей и для всех пользователей не учитывается.
	// 2. Если нет настройки для пользователя, но есть настройка для групп пользователей,
	//    в которые входит пользователь, тогда будет использована настройка для последней
	//    группы пользователей по порядку, а настройки для остальных групп пользователей и
	//    для всех пользователей не учитываются.
	// 3. Если нет настройки для пользователя и нет настроек для групп пользователей, в которые
	//    входит пользователь, тогда будет использоваться настройка для всех пользователей.
	
	// Приоритеты дат запрета загрузки.
	// 1. Если есть настройка для узла информационной базы, то используется она,
	//    а настройки для плана обмена и для всех планов обмена не учитываются.
	// 2. Если нет настройки для узла, но есть настройка для плана обмена, тогда будет
	//    использоваться она, а настройка для всех планов обмена не учитываются.
	// 3. Если нет настройки для узла и нет настройки для плана обмена,
	//    тогда будет использоваться настройка для всех планов обмена.
	
	// Приоритеты по разделам и объектам применяются в пределах приоритетов,
	// описанных выше и одинаковы для дат запрета изменения и загрузки данных.
	// 1. Для раздела, объекта.
	// 2. Для раздела, любого объекта (объект = раздел).
	// 3. Для любого раздела (пустой раздел), любого объекта (объект = раздел).
	
	ЗапретыИзменения = ДанныеДляПроверки.Скопировать(Новый Массив);
	ЗапретыИзменения.Колонки.Добавить("Адресат");
	ЗапретыИзменения.Колонки.Добавить("Данные");
	
	// Поиск запретов изменения данных.
	Если УзелПроверкиЗапретаЗагрузки = Неопределено Тогда
		Адресаты = ДействующиеДаты.ДляПользователей.Адресаты;
		Адресат = Пользователи.АвторизованныйПользователь();
		Разделы = Адресаты.Получить(Адресат);
		Если Разделы = Неопределено Тогда
			ГруппыПользователя = ДействующиеДаты.ГруппыПользователей.Получить(Адресат);
			Если ГруппыПользователя <> Неопределено Тогда
				Для Каждого Группа Из ГруппыПользователя Цикл
					АдресатЗапрета = Группа;
					Разделы = Адресаты.Получить(АдресатЗапрета);
					Прервать;
				КонецЦикла;
			КонецЕсли;
			Если Разделы = Неопределено Тогда
				АдресатЗапрета = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей;
				Разделы = Адресаты.Получить(АдресатЗапрета);
			КонецЕсли;
		КонецЕсли;
	Иначе
		Адресаты = ДействующиеДаты.ДляИнформационныхБаз.Адресаты;
		Адресат = УзелПроверкиЗапретаЗагрузки;
		Разделы = Адресаты.Получить(Адресат);
		Если Разделы = Неопределено Тогда
			АдресатЗапрета = ОбщегоНазначения.МенеджерОбъектаПоСсылке(УзелПроверкиЗапретаЗагрузки).ПустаяСсылка();
			Разделы = Адресаты.Получить(АдресатЗапрета);
			Если Разделы = Неопределено Тогда
				АдресатЗапрета = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехИнформационныхБаз;
				Разделы = Адресаты.Получить(АдресатЗапрета);
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Если Разделы = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Для Каждого Данные Из ДанныеДляПроверки Цикл
		РезультатПоиска = НайтиДатуЗапрета(Разделы, Данные, ПустойРаздел);
		Если РезультатПоиска = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		Если РезультатПоиска.ДатаЗапрета < Данные.Дата Тогда
			Продолжить;
		КонецЕсли;
		
		Строка = ЗапретыИзменения.Добавить();
		Строка.Данные  = Данные;
		Строка.Раздел  = РезультатПоиска.РазделЗапрета;
		Строка.Объект  = РезультатПоиска.ОбъектЗапрета;
		Строка.Адресат = Адресат;
		Строка.Дата    = РезультатПоиска.ДатаЗапрета;
	КонецЦикла;
	
	Если ТипЗнч(ПараметрыСообщенияОЗапрете) = Тип("Структура")
	   И ТипЗнч(ОписаниеОшибки) <> Тип("Null")
	   И ЗапретыИзменения.Количество() > 0 Тогда
		
		ОписаниеОшибки = СообщениеОЗапретах(ЗапретыИзменения, ПараметрыСообщенияОЗапрете, СвойстваРазделов,
			УзелПроверкиЗапретаЗагрузки <> Неопределено, ТипЗнч(ОписаниеОшибки) = Тип("Структура"));
	КонецЕсли;
	
	Возврат ЗапретыИзменения.Количество() > 0;
	
КонецФункции

// Возвращает действующие даты запрета с учетом последней версии после изменений.
//
// Возвращаемое значение:
//   см. ДатыЗапретаИзмененияСлужебный.ЗначениеПараметраСеансаДействующиеДатыЗапретаИзменения
//
Функция ДействующиеДатыЗапрета() Экспорт
	
	ПоследняяПроверка = ДатыЗапретаИзмененияСлужебныйПовтИсп.ПоследняяПроверкаВерсииДействующихДатЗапрета();
	
	ДействующиеДаты = ПараметрыСеанса.ДействующиеДатыЗапретаИзменения;
	
	Если ТекущаяДатаСеанса() > (ПоследняяПроверка.Дата + 5) Тогда
		Если ДействующиеДаты.НачалоДня <> НачалоДня(ТекущаяДатаСеанса())
		 Или ДействующиеДаты.Версия <> Константы.ВерсияДатЗапретаИзменения.Получить() Тогда
			
			УстановитьОтключениеБезопасногоРежима(Истина);
			УстановитьПривилегированныйРежим(Истина);
			
			ОчищаемыеПараметры = Новый Массив;
			ОчищаемыеПараметры.Добавить("ДействующиеДатыЗапретаИзменения");
			ПараметрыСеанса.Очистить(ОчищаемыеПараметры);
			
			УстановитьПривилегированныйРежим(Ложь);
			УстановитьОтключениеБезопасногоРежима(Ложь);
			
			ДействующиеДаты = ПараметрыСеанса.ДействующиеДатыЗапретаИзменения;
		КонецЕсли;
		ПоследняяПроверка.Дата = ТекущаяДатаСеанса();
	КонецЕсли;
	
	Возврат ДействующиеДаты;
	
КонецФункции

// Возвращает источники данных, заполненные в 
// ДатыЗапретаИзмененияПереопределяемый.ЗаполнитьИсточникиДанныхДляПроверкиЗапретаИзменения.
//
// Возвращаемое значение:
//   ФиксированноеСоответствие
//
Функция ИсточникиДанныхДляПроверкиЗапретаИзменения() Экспорт
	
	Возврат ПараметрыСеанса.ДействующиеДатыЗапретаИзменения.ИсточникиДанных;
	
КонецФункции

// Возвращает пустую ссылку указанного типа.
Функция ПустаяСсылка(ТипСсылки)
	
	Типы = Новый Массив;
	Типы.Добавить(ТипСсылки);
	ОписаниеТипов = Новый ОписаниеТипов(Типы);
	
	Возврат ОписаниеТипов.ПривестиЗначение(Неопределено);
	
КонецФункции

Функция ТекстОшибкиДатыЗапретаЗагрузкиНеВнедрены() Экспорт
	
	Возврат НСтр("ru = 'Даты запрета загрузки данных прошлых периодов из других программ
	                   |не предусмотрены ни для одного плана обмена.'");
	
КонецФункции

Функция ЭтоАдресатЗапретаИзменения(АдресатЗапрета) Экспорт
	
	Возврат ТипЗнч(АдресатЗапрета) = Тип("СправочникСсылка.Пользователи")
	    Или ТипЗнч(АдресатЗапрета) = Тип("СправочникСсылка.ГруппыПользователей")
	    Или ТипЗнч(АдресатЗапрета) = Тип("СправочникСсылка.ВнешниеПользователи")
	    Или ТипЗнч(АдресатЗапрета) = Тип("СправочникСсылка.ГруппыВнешнихПользователей")
	    Или АдресатЗапрета = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей;
	
КонецФункции

Функция РассчитанныеДатыЗапретаИзменения() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	ДатыЗапретаИзменения.Раздел КАК Раздел,
	|	ДатыЗапретаИзменения.Объект КАК Объект,
	|	ДатыЗапретаИзменения.Пользователь КАК Пользователь,
	|	ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета,
	|	ДатыЗапретаИзменения.ОписаниеДатыЗапрета КАК ОписаниеДатыЗапрета,
	|	ДатыЗапретаИзменения.Комментарий КАК Комментарий
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";
	Таблица = Запрос.Выполнить().Выгрузить();
	
	НачалоДня = НачалоДня(ТекущаяДатаСеанса());
	Для Каждого Строка Из Таблица Цикл
		Строка.ДатаЗапрета = ДатаЗапретаПоОписанию(Строка.ОписаниеДатыЗапрета,
			Строка.ДатаЗапрета , НачалоДня);
	КонецЦикла;
	
	Возврат Таблица;
	
КонецФункции

// Обновляет план видов характеристик РазделыДатЗапретаИзменения по описанию в метаданных.
Процедура ОбновитьРазделыДатЗапретаИзменения() Экспорт
	
	Если ОбщегоНазначения.РазделениеВключено()
	   И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат;
	КонецЕсли;
	
	СвойстваРазделов = СвойстваРазделов();
	ПустойРаздел = ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.ПустаяСсылка();
	
	ОбновляемыеРазделы = Новый Массив;
	
	Для Каждого ОписаниеРаздела Из СвойстваРазделов.Разделы Цикл
		Если ТипЗнч(ОписаниеРаздела.Ключ) = Тип("Строка")
		 Или Не ЗначениеЗаполнено(ОписаниеРаздела.Ключ) Тогда
			Продолжить;
		КонецЕсли;
		СвойстваРаздела = ОписаниеРаздела.Значение; // см. ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРаздела
		ОбновляемыеРазделы.Добавить(СвойстваРаздела.Ссылка);
		
		НачатьТранзакцию();
		Попытка
			БлокировкаДанных = Новый БлокировкаДанных;
			ЭлементБлокировки = БлокировкаДанных.Добавить("ПланВидовХарактеристик.РазделыДатЗапретаИзменения");
			ЭлементБлокировки.УстановитьЗначение("Ссылка", СвойстваРаздела.Ссылка);
			БлокировкаДанных.Заблокировать();
			
			Объект = СвойстваРаздела.Ссылка.ПолучитьОбъект();
			Записать = Ложь;
			
			Если Объект = Неопределено Тогда
				Объект = ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СоздатьЭлемент();
				Объект.УстановитьСсылкуНового(СвойстваРаздела.Ссылка);
				Записать = Истина;
			КонецЕсли;
			
			Если Объект.Наименование <> СвойстваРаздела.Представление Тогда
				Объект.Наименование = СвойстваРаздела.Представление;
				Записать = Истина;
			КонецЕсли;
			
			Если Объект.ПометкаУдаления Тогда
				Объект.ПометкаУдаления = Ложь;
				Записать = Истина;
			КонецЕсли;
			
			Если ЗначениеЗаполнено(Объект.УдалитьНоваяСсылка) Тогда
				Объект.УдалитьНоваяСсылка = ПустойРаздел;
				Записать = Истина;
			КонецЕсли;
			
			ТипыОбъектов = Новый Массив;
			Если СвойстваРаздела.ТипыОбъектов.Количество() = 0 Тогда
				ТипыОбъектов.Добавить(ТипЗнч(ПустойРаздел));
			Иначе
				Для Каждого СвойстваТипа Из СвойстваРаздела.ТипыОбъектов Цикл
					ТипыОбъектов.Добавить(ТипЗнч(СвойстваТипа.ПустаяСсылка));
				КонецЦикла;
			КонецЕсли;
			Если Объект.ТипЗначения.Типы().Количество() <> ТипыОбъектов.Количество() Тогда
				Объект.ТипЗначения = Новый ОписаниеТипов(ТипыОбъектов);
				Записать = Истина;
			Иначе
				Для Каждого Тип Из ТипыОбъектов Цикл
					Если Не Объект.ТипЗначения.СодержитТип(Тип) Тогда
						Объект.ТипЗначения = Новый ОписаниеТипов(ТипыОбъектов);
						Записать = Истина;
						Прервать;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
			Если Записать Тогда
				ОбновлениеИнформационнойБазы.ЗаписатьОбъект(Объект, Ложь);
			КонецЕсли;
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
			ВызватьИсключение;
		КонецПопытки;
	КонецЦикла;
	
	// Пометка на удаление устаревших непредопределенных разделов.
	НачатьТранзакцию();
	Попытка
		БлокировкаДанных = Новый БлокировкаДанных;
		ЭлементБлокировки = БлокировкаДанных.Добавить("ПланВидовХарактеристик.РазделыДатЗапретаИзменения");
		ЭлементБлокировки.Режим = РежимБлокировкиДанных.Разделяемый;
		БлокировкаДанных.Заблокировать();

		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("Разделы", ОбновляемыеРазделы);
		Запрос.Текст =
		"ВЫБРАТЬ
		|	Разделы.Ссылка КАК Ссылка,
		|	Разделы.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных,
		|	Разделы.УдалитьНоваяСсылка КАК УдалитьНоваяСсылка
		|ИЗ
		|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
		|ГДЕ
		|	НЕ Разделы.ПометкаУдаления
		|	И НЕ Разделы.Ссылка В (&Разделы)
		|	И Разделы.ИмяПредопределенныхДанных = """"";
		
		УстаревшиеРазделы = Запрос.Выполнить().Выгрузить();
		
		ЭлементБлокировки = БлокировкаДанных.Добавить("ПланВидовХарактеристик.РазделыДатЗапретаИзменения");
		ЭлементБлокировки.ИсточникДанных = УстаревшиеРазделы;
		ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Ссылка", "Ссылка");  
		БлокировкаДанных.Заблокировать();
		
		Для каждого УстаревшийРаздел Из УстаревшиеРазделы Цикл
			Если ЗначениеЗаполнено(УстаревшийРаздел.УдалитьНоваяСсылка)
			   И ОбщегоНазначения.РазделениеВключено() Тогда
				Продолжить;
			КонецЕсли;
			Объект = УстаревшийРаздел.Ссылка.ПолучитьОбъект();
			Объект.ПометкаУдаления = Истина;
			ОбновлениеИнформационнойБазы.ЗаписатьДанные(Объект, Ложь);
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

// Обработчик заполнения общей начальной даты запрета изменения до 1980 года.
Процедура УстановитьНачальнуюДатуЗапретаИзменения() Экспорт
	
	УстановитьПривилегированныйРежим(Истина);
	
	НаборЗаписей = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
	НаборЗаписей.Прочитать();
	
	Если НаборЗаписей.Количество() <> 0 Тогда
		Возврат;
	КонецЕсли;
	
	ПустойРаздел = ПустаяСсылка(Тип("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения"));
	
	Запись = НаборЗаписей.Добавить();
	Запись.Пользователь = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей;
	Запись.Раздел       = ПустойРаздел;
	Запись.Объект       = ПустойРаздел;
	Запись.ДатаЗапрета  = '19791231';
	
	ОбновлениеИнформационнойБазы.ЗаписатьДанные(НаборЗаписей);
	
КонецПроцедуры

// Обработчик преобразует план видов характеристик разделы дат запрета изменения.
Процедура ОчиститьПредопределенныеЭлементыРазделовДатЗапрета() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	ИСТИНА КАК ЗначениеИстина
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|ГДЕ
	|	Разделы.ИмяПредопределенныхДанных <> """"";
	
	Если Запрос.Выполнить().Пустой() Тогда
		Возврат;
	КонецЕсли;
	
	СвойстваРазделов = СвойстваРазделов();
	ИменаПредопределенных =
		Метаданные.ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.ПолучитьИменаПредопределенных();
	
	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("ПланВидовХарактеристик.РазделыДатЗапретаИзменения");
	
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Разделы.Ссылка КАК Ссылка,
	|	Разделы.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|ГДЕ
	|	Разделы.ИмяПредопределенныхДанных <> """"";
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		ОбновитьРазделыДатЗапретаИзменения();
		
		Выборка = Запрос.Выполнить().Выбрать();
		Пока Выборка.Следующий() Цикл
			Объект = Выборка.Ссылка.ПолучитьОбъект();
			Если ИменаПредопределенных.Найти(Выборка.ИмяПредопределенныхДанных) <> Неопределено Тогда
				Приставка = "Удалить";
				Если Не СтрНачинаетсяС(Выборка.ИмяПредопределенныхДанных, Приставка) Тогда
					Объект.ПометкаУдаления = Истина;
				Иначе
					ИскомоеИмя = Сред(Выборка.ИмяПредопределенныхДанных, СтрДлина(Приставка) + 1);
					СвойстваРаздела = СвойстваРазделов.Разделы.Получить(ИскомоеИмя); // см. ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРаздела
					
					Если СвойстваРаздела = Неопределено Тогда
						Объект.ПометкаУдаления = Истина;
						
					ИначеЕсли Выборка.Ссылка <> СвойстваРаздела.Ссылка Тогда
						Объект.УдалитьНоваяСсылка = СвойстваРаздела.Ссылка;
						Объект.Наименование = "(" + НСтр("ru = 'не используется'") + ") " + СвойстваРаздела.Представление;
					КонецЕсли;
				КонецЕсли;
			ИначеЕсли СвойстваРазделов.Разделы.Получить(Выборка.Ссылка) = Неопределено Тогда
				Объект.ПометкаУдаления = Истина;
			КонецЕсли;
			Объект.ИмяПредопределенныхДанных = "";
			ОбновлениеИнформационнойБазы.ЗаписатьДанные(Объект, Ложь);
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Обработчик заменяет разделы дат запрета регистре на новые.
Процедура ЗаменитьРазделыДатЗапретаНаНовые() Экспорт
	
	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("РегистрСведений.ДатыЗапретаИзменения");
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Разделы.Ссылка КАК Ссылка,
	|	Разделы.УдалитьНоваяСсылка КАК УдалитьНоваяСсылка
	|ИЗ
	|	ПланВидовХарактеристик.РазделыДатЗапретаИзменения КАК Разделы
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|		ПО (ДатыЗапретаИзменения.Раздел = Разделы.Ссылка)
	|			И (Разделы.УдалитьНоваяСсылка <> ЗНАЧЕНИЕ(ПланВидовХарактеристик.РазделыДатЗапретаИзменения.ПустаяСсылка))";
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		Выборка = Запрос.Выполнить().Выбрать();
		Пока Выборка.Следующий() Цикл
			СтарыеЗаписи = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
			СтарыеЗаписи.Отбор.Раздел.Установить(Выборка.Ссылка);
			СтарыеЗаписи.Прочитать();
			НовыеЗаписи = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
			НовыеЗаписи.Отбор.Раздел.Установить(Выборка.УдалитьНоваяСсылка);
			НовыеЗаписи.Прочитать();
			Если НовыеЗаписи.Количество() > 0 Тогда
				СтарыеЗаписи.Очистить();
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(СтарыеЗаписи, Ложь);
			Иначе
				Для Каждого СтараяЗапись Из СтарыеЗаписи Цикл
					НоваяЗапись = НовыеЗаписи.Добавить();
					ЗаполнитьЗначенияСвойств(НоваяЗапись, СтараяЗапись);
					НоваяЗапись.Раздел = Выборка.УдалитьНоваяСсылка;
					Если СтараяЗапись.Раздел = СтараяЗапись.Объект Тогда
						НоваяЗапись.Объект = Выборка.УдалитьНоваяСсылка;
					КонецЕсли;
				КонецЦикла;
				СтарыеЗаписи.Очистить();
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(СтарыеЗаписи, Ложь);
				ОбновлениеИнформационнойБазы.ЗаписатьДанные(НовыеЗаписи, Ложь);
			КонецЕсли;
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

// Дополняет настройки для пользователей, групп, узлов и планов обмена.
Процедура ДополнитьНастройкиУказанныхАдресатов() Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь,
	|	МАКСИМУМ(ДатыЗапретаИзменения.Комментарий) КАК Комментарий
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|
	|СГРУППИРОВАТЬ ПО
	|	ДатыЗапретаИзменения.Пользователь
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	СоставыГруппПользователей.Пользователь КАК Пользователь,
	|	СоставыГруппПользователей.ГруппаПользователей КАК ГруппаПользователей
	|ИЗ
	|	РегистрСведений.СоставыГруппПользователей КАК СоставыГруппПользователей
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|		ПО СоставыГруппПользователей.ГруппаПользователей = ДатыЗапретаИзменения.Пользователь
	|			И (СоставыГруппПользователей.ГруппаПользователей <> СоставыГруппПользователей.Пользователь)
	|;
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь КАК Пользователь,
	|	ДатыЗапретаИзменения.Раздел КАК Раздел,
	|	ДатыЗапретаИзменения.Объект КАК Объект,
	|	ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета,
	|	ДатыЗапретаИзменения.ОписаниеДатыЗапрета КАК ОписаниеДатыЗапрета
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения";
	
	Блокировка = Новый БлокировкаДанных;
	Блокировка.Добавить("РегистрСведений.ДатыЗапретаИзменения");
	
	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		РезультатыЗапроса = Запрос.ВыполнитьПакет();
		АдресатыНастроек    = РезультатыЗапроса[0].Выгрузить();
		ГруппыПользователей = РезультатыЗапроса[1].Выгрузить();
		Настройки           = РезультатыЗапроса[2].Выгрузить();
		НаборЗаписей = РегистрыСведений.ДатыЗапретаИзменения.СоздатьНаборЗаписей();
		ДобавитьНастройки(НаборЗаписей, Настройки, АдресатыНастроек, ГруппыПользователей, Истина);
		ДобавитьНастройки(НаборЗаписей, Настройки, АдресатыНастроек, ГруппыПользователей, Ложь);
		ОбновлениеИнформационнойБазы.ЗаписатьНаборЗаписей(НаборЗаписей, Ложь);
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// Вспомогательные процедуры и функции.

// Для функции ПроверкаДатЗапретаОтключена.
Функция ЗапретИзмененияДанныхНеИспользуется(ПроверкаЗапретаИзменения, УзелПроверкиЗапретаЗагрузки)
	
	Если ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы() Тогда
		Возврат Истина;
	КонецЕсли;
	
	УстановитьПривилегированныйРежим(Истина);
	
	ДействующиеДатыЗапрета = ДействующиеДатыЗапрета();
	
	Если (Не ДействующиеДатыЗапрета.ЗапретИзмененияИспользуется
	      Или ПроверкаЗапретаИзменения = Ложь)
	   И (Не ДействующиеДатыЗапрета.ЗапретЗагрузкиИспользуется
	      Или УзелПроверкиЗапретаЗагрузки = Неопределено) Тогда
		
		Возврат Истина;
	КонецЕсли;
	
	Возврат Ложь;
	
КонецФункции

// Для функции ИзменениеИлиЗагрузкаЗапрещена.
Функция ДанныеДляПроверкиИзБазыДанных(Данные, ИдентификаторДанных, ДействующиеДаты, УзелПроверкиЗапретаЗагрузки)
	
	Если ТипЗнч(ИдентификаторДанных) = Тип("Отбор") Тогда
		Если ТипЗнч(Данные) = Тип("Строка") Тогда
			ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Данные);
		Иначе
			ОбъектМетаданных = Данные.Метаданные();
		КонецЕсли;
	Иначе
		ОбъектМетаданных = ИдентификаторДанных.Метаданные();
	КонецЕсли;
	
	Таблица = ОбъектМетаданных.ПолноеИмя();
	
	ДанныеДляПроверки = ДатыЗапретаИзменения.ШаблонДанныхДляПроверки();
	ДатыЗапретаИзмененияПереопределяемый.ПередПроверкойСтаройВерсииДанных(ОбъектМетаданных, ИдентификаторДанных,
		УзелПроверкиЗапретаЗагрузки, ДанныеДляПроверки);
		
	Если ДанныеДляПроверки.Количество() > 0 Тогда
		Возврат ДанныеДляПроверки;
	КонецЕсли;
	
	БезОбъекта = ?(УзелПроверкиЗапретаЗагрузки = Неопределено,
		ДействующиеДаты.ДляПользователей.ДатыЗапретаПоОбъектамНеУказаны,
		ДействующиеДаты.ДляИнформационныхБаз.ДатыЗапретаПоОбъектамНеУказаны);
		
	ИсточникиДанных = ПолучитьИсточникиДанных(ДействующиеДаты, Таблица);
	
	ДанныеДляПроверки = ДатыЗапретаИзменения.ШаблонДанныхДляПроверки();
	Запрос = Новый Запрос;
	Если БезОбъекта Тогда
		Запрос.Текст = ИсточникиДанных.ТекстЗапросаТолькоДаты;
	Иначе
		Запрос.Текст = ИсточникиДанных.ТекстЗапроса;
	КонецЕсли;
	Если ИсточникиДанных.ЭтоРегистр Тогда
		ВставитьПараметрыИУсловиеОтбора(Запрос, ИдентификаторДанных);
	Иначе
		Запрос.УстановитьПараметр("Ссылка", ИдентификаторДанных);
	КонецЕсли;
	РезультатыЗапроса = Запрос.ВыполнитьПакет();
	Для Каждого ИсточникДанных Из ИсточникиДанных.Состав Цикл
		Выборка = РезультатыЗапроса[ИсточникиДанных.Состав.Найти(ИсточникДанных)].Выбрать();
		Пока Выборка.Следующий() Цикл
			// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
			ДобавитьСтрокуДанныхИзБазыДанных(Выборка, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
		КонецЦикла;
	КонецЦикла;
	
	Возврат ДанныеДляПроверки;
	
КонецФункции

// Для процедуры ДанныеДляПроверкиИзБазыДанных.
// Преобразует Отбор в условие на языке запросов и вставляет в запрос.
//
// Параметры:
//  Запрос - Запрос
//  Отбор  - Отбор
//
Процедура ВставитьПараметрыИУсловиеОтбора(Запрос, Отбор)
	
	Условие = "";
	Для Каждого ЭлементОтбора Из Отбор Цикл
		Если ЭлементОтбора.Использование Тогда
			Если НЕ ПустаяСтрока(Условие) Тогда
				Условие = Условие + Символы.ПС + "И ";
			КонецЕсли;
			Запрос.УстановитьПараметр(ЭлементОтбора.Имя, ЭлементОтбора.Значение);
			Условие = Условие
				+ "ТекущаяТаблица." + ЭлементОтбора.Имя + " = &" + ЭлементОтбора.Имя;
		КонецЕсли;
	КонецЦикла;
	Условие = ?(ЗначениеЗаполнено(Условие), Условие, "Истина");
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеОтбора", Условие);
	
КонецПроцедуры

// Для функции ИзменениеИлиЗагрузкаЗапрещена.
Функция ДанныеДляПроверкиИзОбъекта(Данные, ДействующиеДаты, УзелПроверкиЗапретаЗагрузки)
	
	ЗначенияПолей = Новый Структура;
	ОбъектМетаданных = Данные.Метаданные();
	
	ДанныеДляПроверки = ДатыЗапретаИзменения.ШаблонДанныхДляПроверки();
	ДатыЗапретаИзмененияПереопределяемый.ПередПроверкойНовойВерсииДанных(ОбъектМетаданных, Данные,
		УзелПроверкиЗапретаЗагрузки, ДанныеДляПроверки);
	
	Если ДанныеДляПроверки.Количество() > 0 Тогда
		Возврат ДанныеДляПроверки;
	КонецЕсли;
	
	БезОбъекта = ?(УзелПроверкиЗапретаЗагрузки = Неопределено,
		ДействующиеДаты.ДляПользователей.ДатыЗапретаПоОбъектамНеУказаны,
		ДействующиеДаты.ДляИнформационныхБаз.ДатыЗапретаПоОбъектамНеУказаны);
	
	Таблица = ОбъектМетаданных.ПолноеИмя();
	ИсточникиДанных = ПолучитьИсточникиДанных(ДействующиеДаты, Таблица);
	
	ДанныеДляПроверки = ДатыЗапретаИзменения.ШаблонДанныхДляПроверки();
	
	Если ИсточникиДанных.ЭтоРегистр Тогда
		ЗначенияПолей = Данные.Выгрузить(, ИсточникиДанных.ПоляРегистра); //  ТаблицаЗначений
		ЗначенияПолей.Свернуть(ИсточникиДанных.ПоляРегистра);
		Если ЗначенияПолей.Колонки.Найти("Регистратор") <> Неопределено
		   И Данные.Отбор.Найти("Регистратор") <> Неопределено
		   И ОбщегоНазначения.ЭтоРегистрСведений(ОбъектМетаданных) Тогда
			ЗначенияПолей.ЗаполнитьЗначения(Данные.Отбор.Регистратор.Значение, "Регистратор");
		КонецЕсли;
		Для Каждого Строка Из ЗначенияПолей Цикл
			Для Каждого ИсточникДанных Из ИсточникиДанных.Состав Цикл
				// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
				ДобавитьСтрокуДанных(Строка, Строка, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
			КонецЦикла;
		КонецЦикла;
	Иначе
		Для Каждого ИсточникДанных Из ИсточникиДанных.Состав Цикл
			
			Если Не ЗначениеЗаполнено(ИсточникДанных.ПолеДаты.ТабличнаяЧасть)
			   И Не ЗначениеЗаполнено(ИсточникДанных.ПолеОбъекта.ТабличнаяЧасть) Тогда
				// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
				ДобавитьСтрокуДанных(Данные, Данные, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
				
			ИначеЕсли Не ЗначениеЗаполнено(ИсточникДанных.ПолеДаты.ТабличнаяЧасть) Тогда
				
				Если БезОбъекта Тогда
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					ДобавитьСтрокуДанных(Данные, Неопределено, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
				Иначе
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					СтрокаДаты = Новый Структура("Значение", ЗначениеПоля(Данные, ИсточникДанных.ПолеДаты));
					Поле = ИсточникДанных.ПолеОбъекта.Имя;
					ЗначенияОбъекта = Данные[ИсточникДанных.ПолеОбъекта.ТабличнаяЧасть].Выгрузить(, Поле); // ТаблицаЗначений
					ЗначенияОбъекта.Свернуть(Поле);
					Для Каждого СтрокаОбъекта Из ЗначенияОбъекта Цикл
						// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
						ДобавитьСтрокуДанных(СтрокаДаты, СтрокаОбъекта, ИсточникДанных, ДанныеДляПроверки);
					КонецЦикла;
				КонецЕсли;
				
			ИначеЕсли Не ЗначениеЗаполнено(ИсточникДанных.ПолеОбъекта.ТабличнаяЧасть) Тогда
				
				Если Не БезОбъекта Тогда
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					СтрокаОбъекта = Новый Структура("Значение", ЗначениеПоля(Данные, ИсточникДанных.ПолеОбъекта));
				КонецЕсли;
				Поле = ИсточникДанных.ПолеДаты.Имя;
				ЗначенияДаты = Данные[ИсточникДанных.ПолеДаты.ТабличнаяЧасть].Выгрузить(, Поле); // ТаблицаЗначений
				ЗначенияДаты.Свернуть(Поле);
				Для Каждого СтрокаДаты Из ЗначенияДаты Цикл
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					ДобавитьСтрокуДанных(СтрокаДаты, СтрокаОбъекта, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
				КонецЦикла;
			
			ИначеЕсли ИсточникДанных.ПолеДаты.ТабличнаяЧасть = ИсточникДанных.ПолеОбъекта.ТабличнаяЧасть Тогда
				
				Если БезОбъекта Тогда
					Поля = ИсточникДанных.ПолеДаты.Имя;
				Иначе
					Поля = ИсточникДанных.ПолеДаты.Имя + "," + ИсточникДанных.ПолеОбъекта.Имя;
				КонецЕсли;
				Значения = Данные[ИсточникДанных.ПолеДаты.ТабличнаяЧасть].Выгрузить(, Поля); // ТаблицаЗначений
				Значения.Свернуть(Поля);
				Для Каждого Строка Из Значения Цикл
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					ДобавитьСтрокуДанных(Строка, Строка, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
				КонецЦикла;
			Иначе
				Поле = ИсточникДанных.ПолеДаты.Имя;
				ЗначенияДаты = Данные[ИсточникДанных.ПолеДаты.ТабличнаяЧасть].Выгрузить(, Поле); // ТаблицаЗначений
				ЗначенияДаты.Свернуть(Поле);
				
				Если Не БезОбъекта Тогда
					Поле = ИсточникДанных.ПолеОбъекта.Имя;
					ЗначенияОбъекта = Данные[ИсточникДанных.ПолеОбъекта.ТабличнаяЧасть].Выгрузить(, Поле); // ТаблицаЗначений
					ЗначенияОбъекта.Свернуть(Поле);
				КонецЕсли;
				
				Для Каждого СтрокаДаты Из ЗначенияДаты Цикл
					// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
					СтрокаДаты = Новый Структура("Значение", ЗначениеПоля(СтрокаДаты, ИсточникДанных.ПолеДаты));
					Если БезОбъекта Тогда
						// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
						ДобавитьСтрокуДанных(СтрокаДаты, Неопределено, ИсточникДанных, ДанныеДляПроверки, БезОбъекта);
					Иначе
						Для Каждого СтрокаОбъекта Из ЗначенияОбъекта Цикл
							// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
							ДобавитьСтрокуДанных(СтрокаДаты, СтрокаОбъекта, ИсточникДанных, ДанныеДляПроверки);
						КонецЦикла;
					КонецЕсли;
				КонецЦикла;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	Возврат ДанныеДляПроверки;
	
КонецФункции

// Для процедур ДанныеДляПроверкиИзБазыДанных, ДанныеДляПроверкиИзОбъекта.
// 
// Параметры:
//  ДействующиеДаты - ФиксированнаяСтруктура
//  Таблица - Строка
// Возвращаемое значение:
//  ФиксированнаяСтруктура:
//    * Состав - ФиксированныйМассив из см. ОписаниеИсточникаДанных
//    * ТекстЗапроса - Строка
//    * ТекстЗапросаТолькоДаты - Строка
//    * ЭтоРегистр - Булево
// 
Функция ПолучитьИсточникиДанных(ДействующиеДаты, Таблица)
	
	ИсточникиДанных = ДействующиеДаты.ИсточникиДанных.Получить(Таблица);
	
	Если ИсточникиДанных = Неопределено
	 Или ИсточникиДанных.Количество() = 0 Тогда
		
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Для таблицы ""%1""
			           |в процедуре %2
			           |общего модуля %3
			           |не указаны источники данных, необходимые для проверки дат запрета.'"),
			Таблица,
			"ЗаполнитьИсточникиДанныхДляПроверкиЗапретаИзменения",
			"ДатыЗапретаИзмененияПереопределяемый");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Возврат ИсточникиДанных;
	
КонецФункции

// Для функции ДанныеДляПроверкиИзБазыДанных.
Процедура ДобавитьСтрокуДанныхИзБазыДанных(Строка, ИсточникДанных, ДанныеДляПроверки, БезОбъекта)
	
	НоваяСтрока = ДанныеДляПроверки.Добавить();
	НоваяСтрока.Раздел = ИсточникДанных.Раздел;
	ПолеДаты = Новый Структура("Имя, Путь", "Дата", ИсточникДанных.ПолеДаты.Путь);
	НоваяСтрока.Дата = ЗначениеПоля(Строка, ПолеДаты);
	
	Если БезОбъекта Или Не ЗначениеЗаполнено(ИсточникДанных.ПолеОбъекта.Имя) Тогда
		Возврат;
	КонецЕсли;
	
	ПолеОбъекта = Новый Структура("Имя, Путь", "Объект", ИсточникДанных.ПолеОбъекта.Путь);
	НоваяСтрока.Объект = ЗначениеПоля(Строка, ПолеОбъекта);
	
КонецПроцедуры

// Для процедуры ДанныеДляПроверкиИзОбъекта.
Процедура ДобавитьСтрокуДанных(СтрокаДаты, СтрокаОбъекта, ИсточникДанных, ДанныеДляПроверки, БезОбъекта = Ложь)
	
	НоваяСтрока = ДанныеДляПроверки.Добавить();
	НоваяСтрока.Раздел = ИсточникДанных.Раздел;
	НоваяСтрока.Дата = ЗначениеПоля(СтрокаДаты, ИсточникДанных.ПолеДаты);
	
	Если БезОбъекта Или Не ЗначениеЗаполнено(ИсточникДанных.ПолеОбъекта.Имя) Тогда
		Возврат;
	КонецЕсли;
	
	НоваяСтрока.Объект = ЗначениеПоля(СтрокаОбъекта, ИсточникДанных.ПолеОбъекта);
	
КонецПроцедуры

// Для процедуры ДобавитьСтрокуДанных.
Функция ЗначениеПоля(ЗначенияПолей, Поле)
	
	Если ТипЗнч(ЗначенияПолей) = Тип("Структура") Тогда
		Возврат ЗначенияПолей.Значение;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(Поле.Путь) Тогда
		Возврат ЗначенияПолей[Поле.Имя];
	КонецЕсли;
	
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ТекущаяТаблица.ПолеПути КАК Значение
	|ИЗ
	|	&ТекущаяТаблица КАК ТекущаяТаблица
	|ГДЕ
	|	ТекущаяТаблица.Ссылка = &ТекущаяСсылка";
	
	ПоляПути = СтрРазделить(Поле.Путь, ".", Ложь);
	ТекущаяСсылка = ЗначенияПолей[Поле.Имя];
	
	Для Каждого ПолеПути Из ПоляПути Цикл
		МетаданныеСсылки = Метаданные.НайтиПоТипу(ТипЗнч(ТекущаяСсылка));
		Если МетаданныеСсылки = Неопределено Тогда
			Возврат Неопределено;
		КонецЕсли;
		Таблица = МетаданныеСсылки.ПолноеИмя();
		ПоляШапки = ДатыЗапретаИзмененияСлужебныйПовтИсп.ПоляШапки(Таблица);
		Если Не ПоляШапки.Свойство(ПолеПути) Тогда
			Возврат Неопределено;
		КонецЕсли;
		Запрос = Новый Запрос;
		Запрос.Текст = СтрЗаменить(ТекстЗапроса, "ПолеПути", ПолеПути);
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ТекущаяТаблица", Таблица);
		Запрос.УстановитьПараметр("ТекущаяСсылка", ТекущаяСсылка);
		// @skip-check query-in-loop - Цикл для исключения разыменования составного типа (стандарт 654)
		Выборка = Запрос.Выполнить().Выбрать();
		Если Не Выборка.Следующий() Тогда
			Возврат Неопределено;
		КонецЕсли;
		ТекущаяСсылка = Выборка.Значение;
	КонецЦикла;
	
	Возврат Выборка.Значение;
	
КонецФункции

// Для процедуры УстановкаПараметровСеанса.
// 
// Возвращаемое значение:
//  ФиксированнаяСтруктура:
//    * Версия - УникальныйИдентификатор
//    * ГруппыПользователей - ФиксированноеСоответствие
//    * ДляИнформационныхБаз - см. УстановленныеДаты
//    * ДляПользователей - см. УстановленныеДаты
//    * ЗапретЗагрузкиИспользуется - Булево
//    * ЗапретИзмененияИспользуется - Булево
//    * ИсточникиДанных - ФиксированноеСоответствие
//    * НачалоДня - Дата
//    * СвойстваРазделов - см. СвойстваРазделов
// 
Функция ЗначениеПараметраСеансаДействующиеДатыЗапретаИзменения() Экспорт
	
	// Смотри приоритеты дат запрета изменения и загрузки данных
	// в функции НайденЗапретИзмененияДанных.
	
	НачалоДня = НачалоДня(ТекущаяДатаСеанса());
	
	ДействующиеДаты = Новый Структура;
	ДействующиеДаты.Вставить("НачалоДня", НачалоДня);
	
	ТипыАдресатов = Метаданные.ОпределяемыеТипы.АдресатЗапретаИзменения.Тип.Типы();
	ТипыАдресатовУзлов = Новый Массив;
	ТипыАдресатовПользователей = Новый Массив;
	Для каждого ТипАдресатов Из ТипыАдресатов Цикл
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипАдресатов);
		Если Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных) Тогда
			ТипыАдресатовУзлов.Добавить(ТипАдресатов);
		ИначеЕсли ТипАдресатов <> Тип("ПеречислениеСсылка.ВидыНазначенияДатЗапрета") Тогда
			ТипыАдресатовПользователей.Добавить(ТипАдресатов);
		КонецЕсли;
	КонецЦикла;
	
	ДействующиеДаты.Вставить("СвойстваРазделов", ТекущиеСвойстваРазделов(ТипыАдресатовУзлов));
	
	Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		РезультатыЗапроса = ЗапросДатЗапретаИзменения().ВыполнитьПакет();
		
		ЗначенияКонстант = РезультатыЗапроса[0].Выгрузить()[0];
		ДействующиеДаты.Вставить("Версия",                      ЗначенияКонстант.ВерсияДатЗапретаИзменения);
		ДействующиеДаты.Вставить("ЗапретИзмененияИспользуется", ЗначенияКонстант.ИспользоватьДатыЗапретаИзменения);
		ДействующиеДаты.Вставить("ЗапретЗагрузкиИспользуется",  ЗначенияКонстант.ИспользоватьДатыЗапретаЗагрузки);
		
		Выгрузка = РезультатыЗапроса[1].Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
		ГруппыПользователей = Новый Соответствие;
		Для Каждого Строка Из Выгрузка.Строки Цикл
			ГруппыПользователей.Вставить(Строка.Пользователь,
				Новый ФиксированныйМассив(Строка.Строки.ВыгрузитьКолонку("ГруппаПользователей")));
		КонецЦикла;
		ДействующиеДаты.Вставить("ГруппыПользователей", Новый ФиксированноеСоответствие(ГруппыПользователей));
		
		ДействующиеДаты.Вставить("ДляПользователей",     УстановленныеДаты(РезультатыЗапроса[2], НачалоДня));
		ДействующиеДаты.Вставить("ДляИнформационныхБаз", УстановленныеДаты(РезультатыЗапроса[3], НачалоДня));
	Иначе
		ДействующиеДаты.Вставить("Версия", ОбщегоНазначенияКлиентСервер.ПустойУникальныйИдентификатор());
		ДействующиеДаты.Вставить("ЗапретИзмененияИспользуется", Ложь);
		ДействующиеДаты.Вставить("ЗапретЗагрузкиИспользуется",  Ложь);
		ДействующиеДаты.Вставить("ГруппыПользователей", Новый ФиксированноеСоответствие(Новый Соответствие));
		УстановленныеДаты = Новый Структура;
		УстановленныеДаты.Вставить("Адресаты", Новый ФиксированноеСоответствие(Новый Соответствие));
		УстановленныеДаты.Вставить("ДатыЗапретаПоОбъектамНеУказаны", Истина);
		ДействующиеДаты.Вставить("ДляПользователей",     Новый ФиксированнаяСтруктура(УстановленныеДаты));
		ДействующиеДаты.Вставить("ДляИнформационныхБаз", Новый ФиксированнаяСтруктура(УстановленныеДаты));
	КонецЕсли;
	
	Если ДействующиеДаты.ДляПользователей.Адресаты.Количество() = 0 Тогда
		ДействующиеДаты.ЗапретИзмененияИспользуется = Ложь;
	КонецЕсли;
	
	Если ДействующиеДаты.ДляИнформационныхБаз.Адресаты.Количество() = 0
	 Или ТипыАдресатовУзлов.Количество() = 0 Тогда
		
		ДействующиеДаты.ЗапретЗагрузкиИспользуется = Ложь;
	КонецЕсли;
	
	ДействующиеДаты.Вставить("ИсточникиДанных", 
		ТекущиеИсточникиДанныхДляПроверкиЗапретаИзменения(ДействующиеДаты.СвойстваРазделов));
	
	Возврат Новый ФиксированнаяСтруктура(ДействующиеДаты);
	
КонецФункции

// Для функции НайденЗапретИзмененияДанных.

Функция НайтиДатуЗапрета(Разделы, Данные, ПустойРаздел)
	
	РазделЗапрета = Данные.Раздел;
	ОбъектЗапрета = Данные.Объект;
	ДатаЗапрета = Неопределено;
	
	Объекты = Разделы.Получить(РазделЗапрета);
	Если Объекты <> Неопределено Тогда
		// Поиск для раздела и объекта.
		ДатаЗапрета = Объекты.Получить(ОбъектЗапрета);
		Если ДатаЗапрета = Неопределено Тогда
			ОбъектЗапрета = РазделЗапрета;
			// Поиск для раздела и любого объекта.
			ДатаЗапрета = Объекты.Получить(ОбъектЗапрета);
		КонецЕсли;
	КонецЕсли;
	
	Если ДатаЗапрета = Неопределено Тогда
		РазделЗапрета = ПустойРаздел;
		ОбъектЗапрета = ПустойРаздел;
		Объекты = Разделы.Получить(РазделЗапрета);
		Если Объекты <> Неопределено Тогда
			// Поиск для любого раздела и любого объекта (общая дата).
			ДатаЗапрета = Объекты.Получить(ОбъектЗапрета);
		КонецЕсли;
	КонецЕсли;
	
	Если ДатаЗапрета = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	РезультатПоиска = Новый Структура;
	РезультатПоиска.Вставить("РазделЗапрета", РазделЗапрета);
	РезультатПоиска.Вставить("ОбъектЗапрета", ОбъектЗапрета);
	РезультатПоиска.Вставить("ДатаЗапрета", ДатаЗапрета);
	
	Возврат РезультатПоиска;
	
КонецФункции

Функция СообщениеОЗапретах(Запреты, ПараметрыСообщенияОЗапрете, СвойстваРазделов, ПоискЗапретовЗагрузки, СтруктурноеОписание)
	
	НоваяВерсия = ПараметрыСообщенияОЗапрете.НоваяВерсия;
	Текст = ПредставлениеДанных(ПараметрыСообщенияОЗапрете.Данные);
	
	Если СтруктурноеОписание Тогда
		ОписаниеОшибки = Новый Структура;
		ОписаниеОшибки.Вставить("ПредставлениеДанных", Текст);
		ОписаниеОшибки.Вставить("Запреты", Новый ТаблицаЗначений);
		Колонки = ОписаниеОшибки.Запреты.Колонки;
		Колонки.Добавить("Дата",            Новый ОписаниеТипов("Дата",,,,,Новый КвалификаторыДаты(ЧастиДаты.Дата)));
		Колонки.Добавить("Раздел",          Новый ОписаниеТипов("Строка",,,,Новый КвалификаторыСтроки(100, ДопустимаяДлина.Переменная)));
		Колонки.Добавить("Объект",          Метаданные.ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.Тип);
		Колонки.Добавить("ДатаЗапрета",     Новый ОписаниеТипов("Дата",,,,,Новый КвалификаторыДаты(ЧастиДаты.Дата)));
		Колонки.Добавить("ОбщаяДата",       Новый ОписаниеТипов("Булево"));
		Колонки.Добавить("ДляВсехОбъектов", Новый ОписаниеТипов("Булево"));
		Колонки.Добавить("Адресат",         Метаданные.ОпределяемыеТипы.АдресатЗапретаИзменения.Тип);
		Колонки.Добавить("Описание",        Новый ОписаниеТипов("Строка",,,,Новый КвалификаторыСтроки(1000,ДопустимаяДлина.Переменная)));
	КонецЕсли;
	
	Если ЗначениеЗаполнено(Текст) Тогда
		Если ПоискЗапретовЗагрузки Тогда
			Если НоваяВерсия Тогда
				Шаблон = НСтр("ru = '%1 невозможно загрузить в запрещенный период.'");
			Иначе
				Шаблон = НСтр("ru = '%1 в запрещенном периоде невозможно заменить загружаемыми данными.'");
			КонецЕсли;
		Иначе
			Если НоваяВерсия Тогда
				Шаблон = НСтр("ru = '%1 невозможно поместить в запрещенный период.'");
			ИначеЕсли ЭтоУдалениеНабораДанных(ПараметрыСообщенияОЗапрете.Данные) Тогда
				Шаблон = НСтр("ru = '%1 невозможно удалить в запрещенном периоде.'");
			Иначе
				Шаблон = НСтр("ru = '%1 невозможно изменить в запрещенном периоде.'");
			КонецЕсли;
		КонецЕсли;
		Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Шаблон, Текст) + Символы.ПС;
		Если Не СтруктурноеОписание Тогда
			Текст = Текст + "[РазделительШапка]";
		КонецЕсли;
		
	КонецЕсли;
	
	ПустойРаздел = ПустаяСсылка(Тип("ПланВидовХарактеристикСсылка.РазделыДатЗапретаИзменения"));
	
	Если СтруктурноеОписание Тогда
		ОписаниеОшибки.Вставить("ЗаголовокОшибки", СокрЛП(Текст));
	Иначе
		ТекстОшибки = Текст;
	КонецЕсли;
	
	ДобавленныеТексты = Новый Соответствие;
	Для Каждого Запрет Из Запреты Цикл
		Текст = СообщениеОЗапрете(Запрет, ПоискЗапретовЗагрузки, СвойстваРазделов, ПустойРаздел);
		
		Если СтруктурноеОписание Тогда
			Текст = СтрЗаменить(Текст, "[РазделительПодробнее]", "");
			
			Проверка = Запрет.Данные;
			СвойстваРаздела = СвойстваРазделов.Разделы.Получить(Проверка.Раздел); // см. ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРаздела
			
			СтрокаОписанияОшибки = ОписаниеОшибки.Запреты.Добавить();
			СтрокаОписанияОшибки.Дата        = Проверка.Дата;
			СтрокаОписанияОшибки.Раздел      = СвойстваРаздела.Имя;
			СтрокаОписанияОшибки.Объект      = ?(Проверка.Объект = Проверка.Раздел, Неопределено, Проверка.Объект);
			СтрокаОписанияОшибки.ДатаЗапрета = Запрет.Дата;
			СтрокаОписанияОшибки.ОбщаяДата   = ?(ЗначениеЗаполнено(Запрет.Раздел), Ложь, Истина);
			СтрокаОписанияОшибки.ДляВсехОбъектов = (Запрет.Раздел = Запрет.Объект);
			СтрокаОписанияОшибки.Адресат  = Запрет.Адресат;
			СтрокаОписанияОшибки.Описание = Текст;
		ИначеЕсли ДобавленныеТексты.Получить(Текст) = Неопределено Тогда
			ДобавленныеТексты.Вставить(Текст, Истина);
			ТекстОшибки = ТекстОшибки + Текст + "[РазделительСообщение]";
		КонецЕсли;
	КонецЦикла;
	
	Если Не СтруктурноеОписание Тогда
		
		РазделительШапка     = "";
		РазделительПодробнее = "";
		РазделительСообщение  = "";
		
		Если ДобавленныеТексты.Количество() > 1 Тогда
			РазделительШапка    = Символы.ПС;
			РазделительСообщение = Символы.ПС + Символы.ПС;
		Иначе
			РазделительПодробнее = Символы.ПС;
		КонецЕсли;
		
		ТекстОшибки = СтрЗаменить(ТекстОшибки, "[РазделительШапка]",     РазделительШапка);
		ТекстОшибки = СтрЗаменить(ТекстОшибки, "[РазделительПодробнее]", РазделительПодробнее);
		ТекстОшибки = СтрЗаменить(ТекстОшибки, "[РазделительСообщение]",  РазделительСообщение);
		
		ОписаниеОшибки = СокрП(ТекстОшибки);
	КонецЕсли;
	
	Возврат ОписаниеОшибки;
	
КонецФункции

Функция СообщениеОЗапрете(Знач Запрет, Знач ПоискЗапретовЗагрузки, Знач СвойстваРазделов, Знач ПустойРаздел)
	
	Если Запрет.Раздел = Запрет.Объект Тогда
		ПоОбъекту = Ложь;
		ПоРазделу = Запрет.Раздел <> ПустойРаздел;
	Иначе
		ПоОбъекту = Истина;
		ПоРазделу = Не ЗначениеЗаполнено(СвойстваРазделов.ЕдинственныйРаздел);
	КонецЕсли;
	
	ДляНеуказанного = Ложь;
	ДляПользователя = Ложь;
	ДляГруппыПользователей = Ложь;
	ДляВсехПользователей = Ложь;
	ДляИнформационнойБазы = Ложь;
	ДляВсехИБПлана = Ложь;
	ДляВсехИБ = Ложь;
	
	Если Запрет.Адресат = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей Тогда
		ДляВсехПользователей = Истина;
		
	ИначеЕсли Запрет.Адресат = Перечисления.ВидыНазначенияДатЗапрета.ДляВсехИнформационныхБаз Тогда
		ДляВсехИБ = Истина;
		
	ИначеЕсли ТипЗнч(Запрет.Адресат) = Тип("СправочникСсылка.ГруппыПользователей")
		ИЛИ ТипЗнч(Запрет.Адресат) = Тип("СправочникСсылка.ГруппыВнешнихПользователей") Тогда
		
		ДляГруппыПользователей = Истина;
		
	ИначеЕсли ТипЗнч(Запрет.Адресат) = Тип("СправочникСсылка.Пользователи") Тогда
		
		Если Запрет.Адресат = Пользователи.СсылкаНеуказанногоПользователя() Тогда
			ДляНеуказанного = Истина;
		Иначе
			ДляПользователя = Истина;
		КонецЕсли;
		
	ИначеЕсли ТипЗнч(Запрет.Адресат) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
		ДляПользователя = Истина;
		
	ИначеЕсли ЗначениеЗаполнено(Запрет.Адресат) Тогда
		ДляИнформационнойБазы = Истина;
	Иначе
		ДляВсехИБПлана = Истина;
	КонецЕсли;
	
	Если Не ПоискЗапретовЗагрузки Тогда
		Если      Не ПоРазделу И Не ПоОбъекту И ДляНеуказанного Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Изменение недоступно, поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляНеуказанного Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Изменение по разделу ""%2"" недоступно 
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляНеуказанного Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Изменение по объекту ""%3"" недоступно,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляНеуказанного Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Изменение по объекту ""%3"" раздела ""%2"" недоступно,
			|поскольку дата %1 входит в запрещенный период по %5'");
		
		ИначеЕсли Не ПоРазделу И Не ПоОбъекту И ДляПользователя Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Пользователю ""%4"" недоступно изменение,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляПользователя Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Пользователю ""%4"" недоступно изменение по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляПользователя Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Пользователю ""%4"" недоступно изменение по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляПользователя Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Пользователю ""%4"" недоступно изменение по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
		
		ИначеЕсли Не ПоРазделу И Не ПоОбъекту И ДляГруппыПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для группы пользователей ""%4"" недоступно изменение,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляГруппыПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для группы пользователей ""%4"" недоступно изменение по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляГруппыПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для группы пользователей ""%4"" недоступно изменение по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляГруппыПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для группы пользователей ""%4"" недоступно изменение по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И Не ПоОбъекту И ДляВсехПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех пользователей недоступно изменение,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляВсехПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех пользователей недоступно изменение по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляВсехПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех пользователей недоступно изменение по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляВсехПользователей Тогда
			
			Текст = НСтр("ru = 'Запрещено изменять данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех пользователей недоступно изменение по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		КонецЕсли;
	Иначе
		Если      Не ПоРазделу И Не ПоОбъекту И ДляИнформационнойБазы Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для информационной базы ""%4"" запрещена загрузка данных,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляИнформационнойБазы Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для информационной базы ""%4"" запрещена загрузка данных по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляИнформационнойБазы Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для информационной базы ""%4"" запрещена загрузка данных по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляИнформационнойБазы Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для информационной базы ""%4"" запрещена загрузка данных по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
		
		ИначеЕсли Не ПоРазделу И Не ПоОбъекту И ДляВсехИБПлана Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз ""%6"" запрещена загрузка данных,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляВсехИБПлана Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз ""%6"" запрещена загрузка данных по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляВсехИБПлана Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз ""%6"" запрещена загрузка данных по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляВсехИБПлана Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз ""%6"" запрещена загрузка данных по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		
		ИначеЕсли Не ПоРазделу И Не ПоОбъекту И ДляВсехИБ Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз запрещена загрузка данных,
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И Не ПоОбъекту И ДляВсехИБ Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз запрещена загрузка данных по разделу ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли Не ПоРазделу И    ПоОбъекту И ДляВсехИБ Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз запрещена загрузка данных по объекту ""%3"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		ИначеЕсли    ПоРазделу И    ПоОбъекту И ДляВсехИБ Тогда
			
			Текст = НСтр("ru = 'Запрещено загружать данные с датой ранее %5 (включительно).
			|[РазделительПодробнее]Подробнее:
			|Для всех информационных баз запрещена загрузка данных по объекту ""%3"" раздела ""%2"",
			|поскольку дата %1 входит в запрещенный период по %5'");
			
		КонецЕсли;
	КонецЕсли;
	
	Если Не СвойстваРазделов.БезРазделовИОбъектов Тогда
		Если ЗначениеЗаполнено(Запрет.Раздел) Тогда
			Если Запрет.Объект = Запрет.Раздел Тогда
				Текст = Текст + " " + НСтр("ru = '(запрет установлен на раздел ""%2"")'");
			ИначеЕсли ЗначениеЗаполнено(СвойстваРазделов.ЕдинственныйРаздел) Тогда
				Текст = Текст + " " + НСтр("ru = '(запрет установлен на объект ""%3"")'");
			Иначе
				Текст = Текст + " " + НСтр("ru = '(запрет установлен на объект ""%3"" раздела ""%2"")'");
			КонецЕсли;
		Иначе
			Текст = Текст + " " + НСтр("ru = '(установлена общая дата запрета)'");
		КонецЕсли;
	КонецЕсли;
	
	Проверка = Запрет.Данные;
	Текст = СтрЗаменить(Текст, "%1", Формат(Проверка.Дата, "ДЛФ=Д"));
	Текст = СтрЗаменить(Текст, "%2", Проверка.Раздел);
	Текст = СтрЗаменить(Текст, "%3", Проверка.Объект);
	Текст = СтрЗаменить(Текст, "%4", Запрет.Адресат);
	Текст = СтрЗаменить(Текст, "%5", Формат(Запрет.Дата, "ДЛФ=Д"));
	Текст = СтрЗаменить(Текст, "%6", Запрет.Адресат.Метаданные().Представление());
	Возврат Текст;

КонецФункции

// Для функции СообщениеОЗапретах.
Функция ПредставлениеДанных(Данные)
	
	Если ТипЗнч(Данные) = Тип("Строка") Тогда
		Возврат СокрЛП(Данные);
	КонецЕсли;
	
	Если ТипЗнч(Данные) = Тип("Структура") Тогда
		ЭтоРегистр = Истина;
		Если ТипЗнч(Данные.Регистр) = Тип("Строка") Тогда
			ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Данные.Регистр);
		Иначе
			ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Данные.Регистр));
		КонецЕсли;
	Иначе
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Данные));
		ЭтоРегистр = ОбщегоНазначения.ЭтоРегистр(ОбъектМетаданных);
	КонецЕсли;
	
	Если ОбъектМетаданных = Неопределено Тогда
		Возврат "";
	КонецЕсли;
	
	Если ЭтоРегистр Тогда
		ПредставлениеДанных = ОбъектМетаданных.Представление();
		
		КоличествоПолей = 0;
		Для каждого ЭлементОтбора Из Данные.Отбор Цикл
			Если ЭлементОтбора.Использование Тогда
				КоличествоПолей = КоличествоПолей + 1;
			КонецЕсли;
		КонецЦикла;
		
		Если КоличествоПолей = 1 Тогда
			ПредставлениеДанных = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = '%1 с полем %2'"),
				ПредставлениеДанных, Строка(Данные.Отбор));
			
		ИначеЕсли КоличествоПолей > 1 Тогда
			ПредставлениеДанных = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = '%1 с полями %2'"),
				ПредставлениеДанных, Строка(Данные.Отбор));
		КонецЕсли;
	Иначе
		ПредставлениеДанных = ОбщегоНазначения.ПредметСтрокой(Данные);
	КонецЕсли;
		
	Возврат ПредставлениеДанных;
	
КонецФункции

// Для функции СообщениеОЗапретах.
Функция ЭтоУдалениеНабораДанных(Данные)
	
	Если ТипЗнч(Данные) = Тип("Структура") И ТипЗнч(Данные.Регистр) <> Тип("Строка") Тогда
		Возврат Данные.Регистр.Количество() = 0; // нет записей в записываемым наборе данных регистра
	КонецЕсли;
	Возврат Ложь;
	
КонецФункции

// Для процедуры ЗначениеПараметраСеансаДействующиеДатыЗапретаИзменения.

Функция ЗапросДатЗапретаИзменения()
	
	// АПК:1377-выкл - №654.2.1 Использование 2 типов "через точку" допустимо,
	// кроме того объем данных небольшой (от единиц до сотен).
	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ
	|	Константы.ВерсияДатЗапретаИзменения КАК ВерсияДатЗапретаИзменения,
	|	Константы.ИспользоватьДатыЗапретаЗагрузки КАК ИспользоватьДатыЗапретаЗагрузки,
	|	Константы.ИспользоватьДатыЗапретаИзменения КАК ИспользоватьДатыЗапретаИзменения
	|ИЗ
	|	Константы КАК Константы
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	СоставыГруппПользователей.Пользователь КАК Пользователь,
	|	СоставыГруппПользователей.ГруппаПользователей КАК ГруппаПользователей,
	|	ДатыЗапретаИзменения.Комментарий КАК Комментарий,
	|	ЕСТЬNULL(СоставыГруппПользователей.ГруппаПользователей.Наименование, """") КАК НаименованиеГруппы
	|ИЗ
	|	РегистрСведений.СоставыГруппПользователей КАК СоставыГруппПользователей
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|		ПО СоставыГруппПользователей.ГруппаПользователей = ДатыЗапретаИзменения.Пользователь
	|			И (СоставыГруппПользователей.ГруппаПользователей <> СоставыГруппПользователей.Пользователь)
	|
	|УПОРЯДОЧИТЬ ПО
	|	Пользователь,
	|	Комментарий УБЫВ,
	|	НаименованиеГруппы УБЫВ
	|ИТОГИ ПО
	|	Пользователь
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь КАК Пользователь,
	|	ДатыЗапретаИзменения.Раздел КАК Раздел,
	|	ДатыЗапретаИзменения.Объект КАК Объект,
	|	ДатыЗапретаИзменения.ОписаниеДатыЗапрета КАК ОписаниеДатыЗапрета,
	|	ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|ГДЕ
	|	(ДатыЗапретаИзменения.Пользователь = ЗНАЧЕНИЕ(Перечисление.ВидыНазначенияДатЗапрета.ДляВсехПользователей)
	|			ИЛИ ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) = ТИП(Справочник.Пользователи)
	|			ИЛИ ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) = ТИП(Справочник.ГруппыПользователей)
	|			ИЛИ ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) = ТИП(Справочник.ВнешниеПользователи)
	|			ИЛИ ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) = ТИП(Справочник.ГруппыВнешнихПользователей))
	|ИТОГИ ПО
	|	Пользователь,
	|	Раздел
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ДатыЗапретаИзменения.Пользователь КАК Пользователь,
	|	ДатыЗапретаИзменения.Раздел КАК Раздел,
	|	ДатыЗапретаИзменения.Объект КАК Объект,
	|	ДатыЗапретаИзменения.ОписаниеДатыЗапрета КАК ОписаниеДатыЗапрета,
	|	ДатыЗапретаИзменения.ДатаЗапрета КАК ДатаЗапрета
	|ИЗ
	|	РегистрСведений.ДатыЗапретаИзменения КАК ДатыЗапретаИзменения
	|ГДЕ
	|	ДатыЗапретаИзменения.Пользователь <> НЕОПРЕДЕЛЕНО
	|	И ДатыЗапретаИзменения.Пользователь <> ЗНАЧЕНИЕ(Перечисление.ВидыНазначенияДатЗапрета.ПустаяСсылка)
	|	И ДатыЗапретаИзменения.Пользователь <> ЗНАЧЕНИЕ(Перечисление.ВидыНазначенияДатЗапрета.ДляВсехПользователей)
	|	И ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) <> ТИП(Справочник.Пользователи)
	|	И ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) <> ТИП(Справочник.ГруппыПользователей)
	|	И ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) <> ТИП(Справочник.ВнешниеПользователи)
	|	И ТИПЗНАЧЕНИЯ(ДатыЗапретаИзменения.Пользователь) <> ТИП(Справочник.ГруппыВнешнихПользователей)
	|ИТОГИ ПО
	|	Пользователь,
	|	Раздел";
	// АПК:1377-вкл.
	
	Возврат Запрос;
	
КонецФункции

// Возвращаемое значение:
//  ФиксированнаяСтруктура:
//   * ДатыЗапретаПоОбъектамНеУказаны - Булево
//   * Адресаты - ФиксированноеСоответствие из КлючИЗначение:
//      ** Ключ     - ОпределяемыйТип.АдресатЗапретаИзменения - адресат.
//      ** Значение - ФиксированноеСоответствие из КлючИЗначение:
//          *** Ключ     - Строка - имя раздела.
//          *** Значение - ФиксированноеСоответствие из КлючИЗначение:
//               **** Ключ     - Характеристика.РазделыДатЗапретаИзменения - объект.
//               **** Значение - Дата - рассчитанная дата запрета.
//  
Функция УстановленныеДаты(РезультатЗапроса, НачалоДня)
	
	Выгрузка = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
	
	Адресаты = Новый Соответствие;
	ДатыЗапретаПоОбъектамНеУказаны = Истина;
	
	Для Каждого Адресат Из Выгрузка.Строки Цикл
		Разделы = Новый Соответствие;
		Для Каждого Раздел Из Адресат.Строки Цикл
			Объекты = Новый Соответствие;
			Для Каждого Объект Из Раздел.Строки Цикл
				Если Раздел.Раздел <> Объект.Объект Тогда
					ДатыЗапретаПоОбъектамНеУказаны = Ложь;
				КонецЕсли;
				Объекты.Вставить(Объект.Объект, ДатаЗапретаПоОписанию(
					Объект.ОписаниеДатыЗапрета, Объект.ДатаЗапрета, НачалоДня));
			КонецЦикла;
			Разделы.Вставить(Раздел.Раздел, Новый ФиксированноеСоответствие(Объекты));
		КонецЦикла;
		Адресаты.Вставить(Адресат.Пользователь, Новый ФиксированноеСоответствие(Разделы));
	КонецЦикла;
	
	УстановленныеДаты = Новый Структура;
	УстановленныеДаты.Вставить("Адресаты", Новый ФиксированноеСоответствие(Адресаты));
	УстановленныеДаты.Вставить("ДатыЗапретаПоОбъектамНеУказаны", ДатыЗапретаПоОбъектамНеУказаны);
	
	Возврат Новый ФиксированнаяСтруктура(УстановленныеДаты);
	
КонецФункции

Функция ТекущиеСвойстваРазделов(ТипыАдресатовУзлов)
	
	Свойства = Новый Структура;
	Свойства.Вставить("ИспользоватьВнешнихПользователей", Ложь);
	
	ДатыЗапретаИзмененияПереопределяемый.НастройкаИнтерфейса(Свойства);
	
	Свойства.Вставить("ДатыЗапретаЗагрузкиВнедрены", ТипыАдресатовУзлов.Количество() > 0);
	
	ПустыеСсылкиУзлов = Новый Массив;
	
	Для Каждого ТипАдресатовУзлов Из ТипыАдресатовУзлов Цикл
		ПустаяСсылкаУзла = ПустаяСсылка(ТипАдресатовУзлов);
		ПустыеСсылкиУзлов.Добавить(ПустаяСсылкаУзла);
	КонецЦикла;
	
	Свойства.Вставить("ПустыеСсылкиУзловПлановОбмена", Новый ФиксированныйМассив(ПустыеСсылкиУзлов));
	
	СвойстваРазделов = ПланыВидовХарактеристик.РазделыДатЗапретаИзменения.СвойстваРазделовДатЗапрета();
	
	Для Каждого КлючИЗначение Из СвойстваРазделов Цикл
		Свойства.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение);
	КонецЦикла;
	
	Возврат Новый ФиксированнаяСтруктура(Свойства);
	
КонецФункции

// Параметры:
//  СвойстваРазделов - см. СвойстваРазделов
//
// Возвращаемое значение:
//  ФиксированноеСоответствие из КлючИЗначение:
//   * Ключ - Строка - имя таблицы
//   * Значение - см. ПолучитьИсточникиДанных
//
Функция ТекущиеИсточникиДанныхДляПроверкиЗапретаИзменения(СвойстваРазделов)
	
	Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
		Возврат Новый ФиксированноеСоответствие(Новый Соответствие);
	КонецЕсли;
	
	ИсточникиДанных = Новый ТаблицаЗначений;
	ИсточникиДанных.Колонки.Добавить("Таблица",     Новый ОписаниеТипов("Строка"));
	ИсточникиДанных.Колонки.Добавить("ПолеДаты",    Новый ОписаниеТипов("Строка"));
	ИсточникиДанных.Колонки.Добавить("Раздел",      Новый ОписаниеТипов("Строка"));
	ИсточникиДанных.Колонки.Добавить("ПолеОбъекта", Новый ОписаниеТипов("Строка"));
	ИсточникиДанных.Индексы.Добавить("Таблица");
	
	ИнтеграцияПодсистемБСП.ПриЗаполненииИсточниковДанныхДляПроверкиЗапретаИзменения(ИсточникиДанных);
	ДатыЗапретаИзмененияПереопределяемый.ЗаполнитьИсточникиДанныхДляПроверкиЗапретаИзменения(ИсточникиДанных);
	
	Источники = Новый Соответствие;
	Таблицы = ИсточникиДанных.Скопировать(, "Таблица");
	Таблицы.Свернуть("Таблица");
	
	ЗаголовокОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Ошибка в процедуре %1
		           |общего модуля %2.'"),
		"ЗаполнитьИсточникиДанныхДляПроверкиЗапретаИзменения",
		"ДатыЗапретаИзмененияПереопределяемый")
		+ Символы.ПС
		+ Символы.ПС;
	
	Для Каждого Строка Из Таблицы Цикл
		ИсточникиТаблицы = Новый Структура;
		ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(Строка.Таблица);
		Если ОбъектМетаданных = Неопределено Тогда
			ТекстОшибки = ЗаголовокОшибки + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения в источнике данных неверно указана таблица
				           |""%1"".'"),
				Строка.Таблица);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
		ЭтоРегистр = СтандартныеПодсистемыСервер.ЭтоТаблицаРегистра(Строка.Таблица);
		ИсточникиТаблицы.Вставить("ЭтоРегистр", ЭтоРегистр);
		
		ИсточникиДанныхТаблицы = ИсточникиДанных.НайтиСтроки(Новый Структура("Таблица", Строка.Таблица));
		СоставИсточников = Новый Массив;
		ПоляРегистра = Новый Соответствие;
		ТекстЗапроса = "";
		ТекстЗапросаТолькоДаты = "";
		Таблица = ОбъектМетаданных.ПолноеИмя();
		
		Для Каждого Строка Из ИсточникиДанныхТаблицы Цикл
			СвойстваРаздела = СвойстваРазделов.Разделы.Получить(Строка.Раздел);
			Если СвойстваРаздела = Неопределено Тогда
				ТекстОшибки = ЗаголовокОшибки + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
					НСтр("ru = 'Для проверки запрета изменения в источнике данных указан несуществующий
					           |раздел ""%1"" для таблицы ""%2""
					           |(см. %3).'"),
					Строка.Раздел,
					Строка.Таблица,
					"ДатыЗапретаИзмененияПереопределяемый.ЗаполнитьИсточникиДанныхДляПроверкиЗапретаИзменения");
				ВызватьИсключение ТекстОшибки;
			КонецЕсли;
			
			Источник = ОписаниеИсточникаДанных();
			Источник.Раздел = Строка.Раздел;
			Источник.ПолеДаты    = ПолеТаблицы(Строка, "ПолеДаты",    ОбъектМетаданных, ЭтоРегистр);
			Источник.ПолеОбъекта = ПолеТаблицы(Строка, "ПолеОбъекта", ОбъектМетаданных, ЭтоРегистр);
			
			Если ЭтоРегистр Тогда
				ПоляРегистра.Вставить(Источник.ПолеДаты.Имя, Истина);
				Если ЗначениеЗаполнено(Источник.ПолеОбъекта.Имя) Тогда
					ДобавитьТекстЗапросаДляРегистра(ТекстЗапроса, Таблица, Источник);
					ПоляРегистра.Вставить(Источник.ПолеОбъекта.Имя, Истина);
				Иначе
					ДобавитьТекстЗапросаТолькоДатыДляРегистра(ТекстЗапроса, Таблица, Источник);
				КонецЕсли;
				ДобавитьТекстЗапросаТолькоДатыДляРегистра(ТекстЗапросаТолькоДаты, Таблица, Источник);
			Иначе
				Если ЗначениеЗаполнено(Источник.ПолеОбъекта.Имя) Тогда
					ДобавитьТекстЗапроса(ТекстЗапроса, Таблица, Источник);
				Иначе
					ДобавитьТекстЗапросаТолькоДаты(ТекстЗапроса, Таблица, Источник);
				КонецЕсли;
				ДобавитьТекстЗапросаТолькоДаты(ТекстЗапросаТолькоДаты, Таблица, Источник);
			КонецЕсли;
			СоставИсточников.Добавить(Новый ФиксированнаяСтруктура(Источник));
		КонецЦикла;
		ИсточникиТаблицы.Вставить("Состав", Новый ФиксированныйМассив(СоставИсточников));
		ИсточникиТаблицы.Вставить("ТекстЗапроса", ТекстЗапроса);
		ИсточникиТаблицы.Вставить("ТекстЗапросаТолькоДаты", ТекстЗапросаТолькоДаты);
		Если ЭтоРегистр Тогда
			Поля = "";
			Для Каждого КлючИЗначение Из ПоляРегистра Цикл
				Поля = Поля + "," + КлючИЗначение.Ключ;
			КонецЦикла;
			ИсточникиТаблицы.Вставить("ПоляРегистра", Сред(Поля, 2));
		КонецЕсли;
		Источники.Вставить(Таблица, Новый ФиксированнаяСтруктура(ИсточникиТаблицы));
	КонецЦикла;
	
	Возврат Новый ФиксированноеСоответствие(Источники);
	
КонецФункции

// Возвращаемое значение:
//   Структура:
//     * Раздел - Произвольный
//     * ПолеДаты - Структура:
//         ** Имя - Строка
//         ** Путь - Строка
//         ** ТабличнаяЧасть - Строка
//     * ПолеОбъекта - Структура:
//         ** Имя - Строка
//         ** Путь - Строка
//         ** ТабличнаяЧасть - Строка
// 
Функция ОписаниеИсточникаДанных()
	
	ПолеДаты    = Новый Структура("Имя, Путь, ТабличнаяЧасть");
	ПолеОбъекта = Новый Структура("Имя, Путь, ТабличнаяЧасть");
	
	Источник = Новый Структура;
	Источник.Вставить("Раздел",      Неопределено);
	Источник.Вставить("ПолеДаты",    ПолеДаты);
	Источник.Вставить("ПолеОбъекта", ПолеОбъекта);
	
	Возврат Источник;
	
КонецФункции

// Для функции ТекущиеИсточникиДанныхДляПроверкиЗапретаИзменения.

Функция ПолеТаблицы(Источник, ВидПоля, ОбъектМетаданных, ЭтоРегистр)
	
	Свойства = Новый Структура("Имя, Путь, ТабличнаяЧасть");
	
	Поле = Источник[ВидПоля];
	Поля = СтрРазделить(Поле, ".", Ложь);
	
	Если Поля.Количество() = 0 Тогда
		Если ВидПоля = "ПолеДаты" Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |не задано поле даты.'"),
				Источник.Таблица);
			ВызватьИсключение ТекстОшибки;
		Иначе
			Возврат Новый ФиксированнаяСтруктура(Свойства);
		КонецЕсли;
		
	ИначеЕсли НЕ ЗначениеЗаполнено(Поля[0]) Тогда
		Если ВидПоля = "ПолеДаты" Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле даты: ""%2""'"),
				Источник.Таблица, Поле);
			ВызватьИсключение ТекстОшибки;
		Иначе
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле объекта: ""%2""'"),
				Источник.Таблица, Поле);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
	КонецЕсли;
	
	Если ЭтоРегистр
	 Или ОбъектМетаданных.ТабличныеЧасти.Найти(Поля[0]) = Неопределено Тогда
		
		Свойства.Имя = Поля[0];
		ПозицияТочки = СтрНайти(Поле, ".");
		Если ПозицияТочки > 0 Тогда
			Свойства.Путь = Сред(Поле, ПозицияТочки + 1);
		КонецЕсли;
		Возврат Новый ФиксированнаяСтруктура(Свойства);
	КонецЕсли;
	
	Если Поля.Количество() = 1 Тогда
		Если ВидПоля = "ПолеДаты" Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле даты:
				           |не задано поле заданной табличной части ""%2"".'"),
				Источник.Таблица, Поля[0]);
			ВызватьИсключение ТекстОшибки;
		Иначе
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле объекта:
				           |не задано поле заданной табличной части ""%2"".'"),
				Источник.Таблица, Поля[0]);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
	ИначеЕсли НЕ ЗначениеЗаполнено(Поля[1]) Тогда
		Если ВидПоля = "ПолеДаты" Тогда
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле даты:
				           |неверно задано поле заданной табличной части ""%2"".'"),
				Источник.Таблица, Поля[0]);
			ВызватьИсключение ТекстОшибки;
		Иначе
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Для проверки запрета изменения 
				           |в источнике данных для таблицы ""%1""
				           |неверно задано поле объекта:
				           |неверно задано поле заданной табличной части ""%2"".'"),
				Источник.Таблица, Поля[0]);
			ВызватьИсключение ТекстОшибки;
		КонецЕсли;
	КонецЕсли;
	
	Свойства.ТабличнаяЧасть = Поля[0];
	Свойства.Имя = Поля[1];
	
	ПозицияТочки = СтрНайти(Поле, ".");
	ИмяИПуть = Сред(Поле, ПозицияТочки + 1);
	
	ПозицияТочки = СтрНайти(ИмяИПуть, ".");
	Если ПозицияТочки > 0 Тогда
		Свойства.Путь = Сред(ИмяИПуть, ПозицияТочки + 1);
	КонецЕсли;
	
	Возврат Новый ФиксированнаяСтруктура(Свойства);
	
КонецФункции

Процедура ДобавитьТекстЗапроса(ТекстЗапроса, Таблица, Источник)
	
	Если Не ЗначениеЗаполнено(Источник.ПолеДаты.ТабличнаяЧасть)
	   И Не ЗначениеЗаполнено(Источник.ПолеОбъекта.ТабличнаяЧасть)
	 Или Источник.ПолеДаты.ТабличнаяЧасть = Источник.ПолеОбъекта.ТабличнаяЧасть Тогда
		
		Если Источник.ПолеДаты.ТабличнаяЧасть = Источник.ПолеОбъекта.ТабличнаяЧасть Тогда
			ТекущаяТаблица = Таблица + "." + Источник.ПолеДаты.ТабличнаяЧасть;
		Иначе
			ТекущаяТаблица = Таблица;
		КонецЕсли;
		
		Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	&ПолеДаты КАК Дата,
		|	&ПолеОбъекта КАК Объект
		|ИЗ
		|	&Таблица КАК ТекущаяТаблица
		|ГДЕ
		|	ТекущаяТаблица.Ссылка = &Ссылка";
		Текст = СтрЗаменить(Текст, "&Таблица",     ТекущаяТаблица);
		Текст = СтрЗаменить(Текст, "&ПолеДаты",    "ТекущаяТаблица." + Источник.ПолеДаты.Имя);
		Текст = СтрЗаменить(Текст, "&ПолеОбъекта", "ТекущаяТаблица." + Источник.ПолеОбъекта.Имя);
	Иначе
		Если ЗначениеЗаполнено(Источник.ПолеДаты.ТабличнаяЧасть) Тогда
			ТаблицаПоляДаты = Таблица + "." + Источник.ПолеДаты.ТабличнаяЧасть;
		Иначе
			ТаблицаПоляДаты = Таблица;
		КонецЕсли;
		
		Если ЗначениеЗаполнено(Источник.ПолеОбъекта.ТабличнаяЧасть) Тогда
			ТаблицаПоляОбъекта = Таблица + "." + Источник.ПолеОбъекта.ТабличнаяЧасть;
		Иначе
			ТаблицаПоляОбъекта = Таблица;
		КонецЕсли;
		
		Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	&ПолеДаты КАК Дата,
		|	&ПолеОбъекта КАК Объект
		|ИЗ
		|	ТаблицаДаты КАК ТаблицаПоляДаты
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаОбъекта КАК ТаблицаПоляОбъекта
		|		ПО (ТаблицаПоляДаты.Ссылка = &Ссылка)
		|			И (ТаблицаПоляОбъекта.Ссылка = &Ссылка)";
		Текст = СтрЗаменить(Текст, "ТаблицаДаты",    ТаблицаПоляДаты);
		Текст = СтрЗаменить(Текст, "ТаблицаОбъекта", ТаблицаПоляОбъекта);
		Текст = СтрЗаменить(Текст, "&ПолеДаты",    "ТаблицаПоляДаты."    + Источник.ПолеДаты.Имя);
		Текст = СтрЗаменить(Текст, "&ПолеОбъекта", "ТаблицаПоляОбъекта." + Источник.ПолеОбъекта.Имя);
	КонецЕсли;
	
	ДобавитьТекстЗапросаВПакет(ТекстЗапроса, Текст);
	
КонецПроцедуры

Процедура ДобавитьТекстЗапросаТолькоДаты(ТекстЗапроса, Таблица, Источник)
	
	Если Не ЗначениеЗаполнено(Источник.ПолеДаты.ТабличнаяЧасть) Тогда
		Текст =
		"ВЫБРАТЬ
		|	&ПолеДаты КАК Дата
		|ИЗ
		|	&Таблица КАК ТекущаяТаблица
		|ГДЕ
		|	ТекущаяТаблица.Ссылка = &Ссылка";
		Текст = СтрЗаменить(Текст, "&Таблица", Таблица);
		Текст = СтрЗаменить(Текст, "&ПолеДаты", "ТекущаяТаблица." + Источник.ПолеДаты.Имя);
	Иначе
		Если ЗначениеЗаполнено(Источник.ПолеДаты.Путь) Тогда
			Текст =
			"ВЫБРАТЬ РАЗЛИЧНЫЕ
			|	&ПолеДаты КАК Дата
			|ИЗ
			|	&Таблица КАК ТекущаяТаблица
			|ГДЕ
			|	ТекущаяТаблица.Ссылка = &Ссылка";
		Иначе
			Текст =
			"ВЫБРАТЬ ПЕРВЫЕ 1
			|	ВЫРАЗИТЬ(&ПолеДаты КАК ДАТА) КАК Дата
			|ИЗ
			|	&Таблица КАК ТекущаяТаблица
			|ГДЕ
			|	ТекущаяТаблица.Ссылка = &Ссылка
			|
			|УПОРЯДОЧИТЬ ПО
			|	Дата";
		КонецЕсли;
		Текст = СтрЗаменить(Текст, "&Таблица", Таблица + "." + Источник.ПолеДаты.ТабличнаяЧасть);
		Текст = СтрЗаменить(Текст, "&ПолеДаты", "ТекущаяТаблица." + Источник.ПолеДаты.Имя);
	КонецЕсли;
	
	ДобавитьТекстЗапросаВПакет(ТекстЗапроса, Текст);
	
КонецПроцедуры

Процедура ДобавитьТекстЗапросаДляРегистра(ТекстЗапроса, Таблица, Источник)
	
	Текст =
	"ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	&ПолеДаты КАК Дата,
	|	&ПолеОбъекта КАК Объект
	|ИЗ
	|	&Таблица КАК ТекущаяТаблица
	|ГДЕ
	|	&УсловиеОтбора";
	
	Текст = СтрЗаменить(Текст, "&Таблица", Таблица);
	Текст = СтрЗаменить(Текст, "&ПолеДаты",    "ТекущаяТаблица." + Источник.ПолеДаты.Имя);
	Текст = СтрЗаменить(Текст, "&ПолеОбъекта", "ТекущаяТаблица." + Источник.ПолеОбъекта.Имя);
	
	ДобавитьТекстЗапросаВПакет(ТекстЗапроса, Текст);
	
КонецПроцедуры

Процедура ДобавитьТекстЗапросаТолькоДатыДляРегистра(ТекстЗапроса, Таблица, Источник)
	
	Если ЗначениеЗаполнено(Источник.ПолеДаты.Путь) Тогда
		Текст =
		"ВЫБРАТЬ РАЗЛИЧНЫЕ
		|	&ПолеДаты КАК Дата
		|ИЗ
		|	&Таблица КАК ТекущаяТаблица
		|ГДЕ
		|	&УсловиеОтбора";
	Иначе
		Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ВЫРАЗИТЬ(&ПолеДаты КАК ДАТА) КАК Дата
		|ИЗ
		|	&Таблица КАК ТекущаяТаблица
		|ГДЕ
		|	&УсловиеОтбора
		|
		|УПОРЯДОЧИТЬ ПО
		|	Дата";
	КонецЕсли;
	
	Текст = СтрЗаменить(Текст, "&Таблица", Таблица);
	Текст = СтрЗаменить(Текст, "&ПолеДаты", "ТекущаяТаблица." + Источник.ПолеДаты.Имя);
	
	ДобавитьТекстЗапросаВПакет(ТекстЗапроса, Текст);
	
КонецПроцедуры

Процедура ДобавитьТекстЗапросаВПакет(ТекстПакетаЗапросов, ТекстЗапроса)
	
	Если Не ЗначениеЗаполнено(ТекстПакетаЗапросов) Тогда
		ТекстПакетаЗапросов = ТекстЗапроса;
		Возврат;
	КонецЕсли;
	
	ТекстПакетаЗапросов = ТекстПакетаЗапросов + "
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|" + ТекстЗапроса;
	
КонецПроцедуры

// Для процедур ПриОтправкеДанныхГлавному, ПриОтправкеДанныхГлавному,
// ПриПолученииДанныхОтГлавного, ПриПолученииДанныхОтПодчиненного.
//
Функция НаборЗаписейТолькоСДатамиЗапретаЗагрузки(ЭлементДанных)
	
	Если ТипЗнч(ЭлементДанных) <> Тип("РегистрСведенийНаборЗаписей.ДатыЗапретаИзменения") Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Если Не ЭлементДанных.Отбор.Пользователь.Использование Тогда
		ТекстОшибки =
			НСтр("ru = 'Выгрузка или загрузка записей регистра сведений ""Даты запрета изменения""
			           |допускается только в разрезе измерения Пользователь.'");
		ВызватьИсключение ТекстОшибки;
	КонецЕсли;
	
	Возврат Не ЭтоАдресатЗапретаИзменения(ЭлементДанных.Отбор.Пользователь.Значение);
	
КонецФункции

// Для процедуры ДополнитьНастройкиУказанныхАдресатов.
Процедура ДобавитьНастройки(НаборЗаписей, Настройки, АдресатыНастроек, ГруппыПользователей, НастройкиГрупп)
	
	Для Каждого АдресатНастроек Из АдресатыНастроек Цикл
		Адресат = АдресатНастроек.Пользователь;
		ТипАдресата = ТипЗнч(Адресат);
		ОбъектМетаданныхАдресата = Метаданные.НайтиПоТипу(ТипАдресата);
		ЭтоПланОбмена = ТипЗнч(ОбъектМетаданныхАдресата) = Тип("ОбъектМетаданных")
			И Метаданные.ПланыОбмена.Содержит(ОбъектМетаданныхАдресата);
		Если ТипАдресата = Тип("ПеречислениеСсылка.ВидыНазначенияДатЗапрета")
		 Или Не ЗначениеЗаполнено(Адресат)
		   И Не ЭтоПланОбмена
		 Или НастройкиГрупп
		   И Не (    ТипЗнч(Адресат) = Тип("СправочникСсылка.Пользователи")
		         Или ТипЗнч(Адресат) = Тип("СправочникСсылка.ВнешниеПользователи")
		         Или ЭтоПланОбмена
		           И ЗначениеЗаполнено(Адресат)) Тогда
			Продолжить;
		КонецЕсли;
		
		Если Не НастройкиГрупп Тогда
			Отбор = Новый Структура("Пользователь", ?(ЭтоПланОбмена,
				Перечисления.ВидыНазначенияДатЗапрета.ДляВсехИнформационныхБаз,
				Перечисления.ВидыНазначенияДатЗапрета.ДляВсехПользователей));
			ДополнительныеНастройки = Настройки.НайтиСтроки(Отбор);
			
		ИначеЕсли ТипЗнч(Адресат) <> Тип("СправочникСсылка.Пользователи")
		        И ТипЗнч(Адресат) <> Тип("СправочникСсылка.ВнешниеПользователи") Тогда
			
			Типы = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ТипАдресата);
			ОписаниеТипов = Новый ОписаниеТипов(Типы);
			ПустойУзел = ОписаниеТипов.ПривестиЗначение(Неопределено);
			Отбор = Новый Структура("Пользователь", ПустойУзел);
			ДополнительныеНастройки = Настройки.НайтиСтроки(Отбор);
		Иначе
			Отбор = Новый Структура("Пользователь", Адресат);
			Строки = ГруппыПользователей.НайтиСтроки(Отбор);
			ДополнительныеНастройки = Настройки.Скопировать(Новый Массив);
			Для Каждого Строка Из Строки Цикл
				Отбор = Новый Структура("Пользователь", Строка.ГруппаПользователей);
				НастройкиГруппы = Настройки.НайтиСтроки(Отбор);
				Для Каждого НастройкаГруппы Из НастройкиГруппы Цикл
					Отбор = Новый Структура("Раздел, Объект", НастройкаГруппы.Раздел, НастройкаГруппы.Объект);
					СуществующиеНастройки = ДополнительныеНастройки.НайтиСтроки(Отбор);
					Если СуществующиеНастройки.Количество() > 0 Тогда
						СуществующаяНастройка = СуществующиеНастройки[0];
						Если ДатаЗапретаМеньше(НастройкаГруппы, СуществующаяНастройка) Тогда
							Продолжить;
						Иначе
							ДополнительныеНастройки.Удалить(СуществующаяНастройка);
						КонецЕсли;
					КонецЕсли;
					ЗаполнитьЗначенияСвойств(ДополнительныеНастройки.Добавить(), НастройкаГруппы);
				КонецЦикла;
			КонецЦикла;
		КонецЕсли;
		
		Для Каждого Строка Из ДополнительныеНастройки Цикл
			Отбор = Новый Структура("Пользователь, Раздел, Объект",
				АдресатНастроек.Пользователь, Строка.Раздел, Строка.Объект);
			Если Настройки.НайтиСтроки(Отбор).Количество() > 0 Тогда
				Продолжить;
			КонецЕсли;
			НоваяСтрока = НаборЗаписей.Добавить();
			ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
			ЗаполнитьЗначенияСвойств(НоваяСтрока, АдресатНастроек);
			ЗаполнитьЗначенияСвойств(Настройки.Добавить(), НоваяСтрока);
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

// Для процедуры ДобавитьНастройки.
Функция ДатаЗапретаМеньше(ПерваяНастройка, ВтораяНастройка)
	
	Если ЗначениеЗаполнено(ПерваяНастройка.ОписаниеДатыЗапрета)
	   И ЗначениеЗаполнено(ВтораяНастройка.ОписаниеДатыЗапрета) Тогда
		
		Возврат ИнтервалОтносительнойДатыЗапрета(ПерваяНастройка.ОписаниеДатыЗапрета)
		      > ИнтервалОтносительнойДатыЗапрета(ВтораяНастройка.ОписаниеДатыЗапрета);
	КонецЕсли;
	
	Возврат ДатаЗапретаПоОписанию(ПерваяНастройка.ОписаниеДатыЗапрета, ПерваяНастройка.ДатаЗапрета)
	      < ДатаЗапретаПоОписанию(ВтораяНастройка.ОписаниеДатыЗапрета, ВтораяНастройка.ДатаЗапрета);
	
КонецФункции

// Для функции ДатаЗапретаМеньше.
Функция ИнтервалОтносительнойДатыЗапрета(ОписаниеДатыЗапрета)
	
	ВариантДатыЗапрета    = СтрПолучитьСтроку(ОписаниеДатыЗапрета, 1);
	КоличествоДнейСтрокой = СтрПолучитьСтроку(ОписаниеДатыЗапрета, 2);
	
	Если ЗначениеЗаполнено(КоличествоДнейСтрокой) Тогда
		ОписаниеТипа = Новый ОписаниеТипов("Число");
		КоличествоДнейРазрешения = ОписаниеТипа.ПривестиЗначение(КоличествоДнейСтрокой);
	Иначе
		КоличествоДнейРазрешения = 0;
	КонецЕсли;
	
	Интервал = 10;
	
	Если ВариантДатыЗапрета = "КонецПрошлогоГода" Тогда
		Интервал = 5;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлогоКвартала" Тогда
		Интервал = 4;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлогоМесяца" Тогда
		Интервал = 3;
		
	ИначеЕсли ВариантДатыЗапрета = "КонецПрошлойНедели" Тогда
		Интервал = 2;
		
	ИначеЕсли ВариантДатыЗапрета = "ПредыдущийДень" Тогда
		Интервал = 1;
	КонецЕсли;
	
	Возврат Интервал * 1000 + КоличествоДнейРазрешения;
	
КонецФункции

#КонецОбласти
